Mailpark
API reference

Contacts

The people you email. A contact is keyed by email address; POST /v1/contacts creates or updates. fields hold anything you want in templates ({{first_name}}), topics hold per-topic marketing consent.

Contacts are also created automatically when you send to or record an event for a new address.

The Contact object
type Contact = {
  id: string;                      // con_…
  email: string;
  external_id: string | null;      // your user id
  fields: Record<string, string | number | boolean | null>;
  topics: Record<string, boolean>; // topic -> subscribed
  lists: string[];                 // contact list ids
  status: "active" | "unsubscribed" | "bounced" | "complained";
  flags: ("role_address" | "disposable_domain" | "no_mx")[];
  ev: Record<string, { first: string; last: string; count: number }>; // event summary
  created_at: string; updated_at: string;
};

Create or update a contact

POST/v1/contacts

Creates the contact, or updates it if the email already exists. Fields are merged; lists only adds.

scope contacts:write

Body

  • emailstringrequired

    The contact's address.

  • external_idstring

    Your own user id.

  • fieldsobject

    Values for templates and audience filters, e.g. { first_name, plan }.

  • topicsobject

    Topic consent: { "product-updates": true }.

  • listsstring[]

    List ids to add the contact to.

curl -X POST https://api.mailpark.io/v1/contacts \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "jane@example.com",
    "external_id": "user_123",
    "fields": {
      "first_name": "Jane",
      "plan": "trial"
    }
  }'
Response · 200
{
  "id": "con_7Yt1",
  "email": "jane@example.com",
  "external_id": "user_123",
  "fields": {
    "first_name": "Jane",
    "plan": "trial"
  },
  "topics": {
    "product-updates": true,
    "onboarding": true
  },
  "lists": [
    "lst_beta"
  ],
  "status": "active",
  "flags": [],
  "ev": {
    "signed_up": {
      "first": "2026-10-20T09:00:00Z",
      "last": "2026-10-20T09:00:00Z",
      "count": 1
    }
  },
  "created_at": "2026-10-20T09:00:00Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

List contacts

GET/v1/contacts

Contacts, newest first.

scope logs:read

Query parameters

  • statusstring

    active, unsubscribed, bounced or complained.

  • topicstring

    Only contacts subscribed to this topic.

  • liststring

    Only members of this list id.

  • limitinteger

    How many to return, 1–100. Default 50.

  • cursorstring

    The next_cursor from the previous page.

curl 'https://api.mailpark.io/v1/contacts?status=active' \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "data": [
    {
      "id": "con_7Yt1",
      "email": "jane@example.com",
      "external_id": "user_123",
      "fields": {
        "first_name": "Jane",
        "plan": "trial"
      },
      "topics": {
        "product-updates": true,
        "onboarding": true
      },
      "lists": [
        "lst_beta"
      ],
      "status": "active",
      "flags": [],
      "ev": {
        "signed_up": {
          "first": "2026-10-20T09:00:00Z",
          "last": "2026-10-20T09:00:00Z",
          "count": 1
        }
      },
      "created_at": "2026-10-20T09:00:00Z",
      "updated_at": "2026-10-22T10:02:11Z"
    }
  ],
  "next_cursor": null
}
▶ Try it in the playground

Get a contact

GET/v1/contacts/{id_or_email}

One contact by id or email address.

Path parameters

  • id_or_emailstringrequired

    con_… or the email address.

curl https://api.mailpark.io/v1/contacts/jane%40example.com \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "id": "con_7Yt1",
  "email": "jane@example.com",
  "external_id": "user_123",
  "fields": {
    "first_name": "Jane",
    "plan": "trial"
  },
  "topics": {
    "product-updates": true,
    "onboarding": true
  },
  "lists": [
    "lst_beta"
  ],
  "status": "active",
  "flags": [],
  "ev": {
    "signed_up": {
      "first": "2026-10-20T09:00:00Z",
      "last": "2026-10-20T09:00:00Z",
      "count": 1
    }
  },
  "created_at": "2026-10-20T09:00:00Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

Update a contact

PATCH/v1/contacts/{id_or_email}

Changes fields, topics, external id or lists. Here lists replaces the contact's list memberships.

scope contacts:write

Path parameters

  • id_or_emailstringrequired

    con_… or the email address.

Body

  • fieldsobject

    Merged into the existing fields. null removes a field.

  • topicsobject

    Topic consent to change.

  • external_idstring

    Your own user id.

  • listsstring[]

    The full set of list ids.

curl -X PATCH https://api.mailpark.io/v1/contacts/jane%40example.com \
  -H "Authorization: Bearer $MAILPARK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fields": {
      "plan": "pro"
    },
    "topics": {
      "product-updates": false
    }
  }'
Response · 200
{
  "id": "con_7Yt1",
  "email": "jane@example.com",
  "external_id": "user_123",
  "fields": {
    "first_name": "Jane",
    "plan": "pro"
  },
  "topics": {
    "product-updates": false,
    "onboarding": true
  },
  "lists": [
    "lst_beta"
  ],
  "status": "active",
  "flags": [],
  "ev": {
    "signed_up": {
      "first": "2026-10-20T09:00:00Z",
      "last": "2026-10-20T09:00:00Z",
      "count": 1
    }
  },
  "created_at": "2026-10-20T09:00:00Z",
  "updated_at": "2026-10-22T10:02:11Z"
}
▶ Try it in the playground

Delete a contact

DELETE/v1/contacts/{id_or_email}

Removes the contact's personal data everywhere: fields, events, list memberships and enrollments. Use it for deletion requests.

scope contacts:write

Path parameters

  • id_or_emailstringrequired

    con_… or the email address.

curl -X DELETE https://api.mailpark.io/v1/contacts/jane%40example.com \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "deleted": true,
  "id": "con_7Yt1"
}
▶ Try it in the playground

Count contacts

GET/v1/contacts/summary

Totals: all contacts, subscribed (status active), and new in the last 30 days against the 30 before.

scope logs:read
curl https://api.mailpark.io/v1/contacts/summary \
  -H "Authorization: Bearer $MAILPARK_API_KEY"
Response · 200
{
  "total": 4820,
  "subscribed": 4511,
  "new_30d": 612,
  "new_prev_30d": 540
}
▶ Try it in the playground