New: the MailCraft MCP server is live โ€” connect your AI agent in one line. Connect your agent โ†’
API reference

Contacts

Upsert and manage contacts, including custom properties and list membership.

Upsert a contact

Creates the contact if the email is new, otherwise updates the existing one. `properties` merges into the JSON properties column.

POST
/contacts

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

Body ยท application/json

email
string
first_name
string
last_name
string
properties
object
Upsert a contact
curl https://api.mailcraft.host/v1/contacts \
  -X POST \
  -H 'Authorization: Bearer sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "[email protected]",
    "first_name": "Jamie",
    "last_name": "Rivera",
    "properties": { "plan": "pro", "signup_source": "website" }
  }'
{
  "data": {
    "id": "01j9x2h6w9q3b6xk0m2v8r5tzn",
    "email": "[email protected]",
    "first_name": "Jamie",
    "last_name": "Rivera",
    "status": "subscribed",
    "properties": { "plan": "pro", "signup_source": "website" },
    "subscribed_at": "2026-09-22T14:05:00.000000Z",
    "unsubscribed_at": null,
    "created_at": "2026-09-22T14:05:00.000000Z"
  }
}

List contacts

Cursor-paginated, newest first. Pass `limit` (default 25) and the `next_cursor` from `meta` to page forward.

GET
/contacts

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

List contacts
curl https://api.mailcraft.host/v1/contacts?limit=25 \
  -H 'Authorization: Bearer sk_live_...'
{
  "data": [
    {
      "id": "01j9x2h6w9q3b6xk0m2v8r5tzn",
      "email": "[email protected]",
      "first_name": "Jamie",
      "last_name": "Rivera",
      "status": "subscribed",
      "properties": { "plan": "pro" },
      "created_at": "2026-09-22T14:05:00.000000Z"
    }
  ],
  "meta": { "next_cursor": null, "prev_cursor": null }
}

Get a contact

Fetches a single contact by id, including their current custom properties.

GET
/contacts/{id}

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

Get a contact
curl https://api.mailcraft.host/v1/contacts/01j9x2h6w9q3b6xk0m2v8r5tzn \
  -H 'Authorization: Bearer sk_live_...'
{
  "data": {
    "id": "01j9x2h6w9q3b6xk0m2v8r5tzn",
    "email": "[email protected]",
    "first_name": "Jamie",
    "last_name": "Rivera",
    "status": "subscribed",
    "properties": { "plan": "pro" },
    "subscribed_at": "2026-09-22T14:05:00.000000Z",
    "unsubscribed_at": null,
    "created_at": "2026-09-22T14:05:00.000000Z"
  }
}

Delete a contact

Permanently removes the contact and their list memberships. Does not add the address to the suppression list.

DELETE
/contacts/{id}

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

Delete a contact
curl https://api.mailcraft.host/v1/contacts/01j9x2h6w9q3b6xk0m2v8r5tzn \
  -X DELETE \
  -H 'Authorization: Bearer sk_live_...'
(empty body)

Unsubscribe a contact

Sets `status` to `unsubscribed` and stamps `unsubscribed_at`. Does not add the address to the suppression list โ€” pair with the Suppressions API if the unsubscribe should also block transactional sends.

POST
/contacts/{id}/unsubscribe

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

Unsubscribe a contact
curl https://api.mailcraft.host/v1/contacts/01j9x2h6w9q3b6xk0m2v8r5tzn/unsubscribe \
  -X POST \
  -H 'Authorization: Bearer sk_live_...'
{
  "data": {
    "id": "01j9x2h6w9q3b6xk0m2v8r5tzn",
    "email": "[email protected]",
    "status": "unsubscribed",
    "subscribed_at": "2026-09-22T14:05:00.000000Z",
    "unsubscribed_at": "2026-09-22T15:10:00.000000Z"
  }
}

Add a contact to list(s)

Adds the contact to one or more static lists, creating each membership if it does not already exist.

POST
/contacts/{id}/lists

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

Body ยท application/json

list_ids
number[]
Add a contact to list(s)
curl https://api.mailcraft.host/v1/contacts/01j9x2h6w9q3b6xk0m2v8r5tzn/lists \
  -X POST \
  -H 'Authorization: Bearer sk_live_...' \
  -H 'Content-Type: application/json' \
  -d '{ "list_ids": [4, 7] }'
{
  "data": [
    { "id": 4, "name": "Newsletter", "type": "static" },
    { "id": 7, "name": "Trial users", "type": "static" }
  ]
}

List a contact's lists

Returns every list the contact currently belongs to.

GET
/contacts/{id}/lists

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

List a contact's lists
curl https://api.mailcraft.host/v1/contacts/01j9x2h6w9q3b6xk0m2v8r5tzn/lists \
  -H 'Authorization: Bearer sk_live_...'
{
  "data": [
    {
      "id": 4,
      "name": "Newsletter",
      "type": "static",
      "segment_id": null,
      "properties": [{ "id": 3, "key": "plan", "label": "Plan", "type": "text" }]
    }
  ]
}

Remove a contact from a list

Removes the contact from a single static list. Has no effect on dynamic list membership, which is computed from a segment.

DELETE
/contacts/{id}/lists/{list}

Authorizations

Authorization
string
header
required

API key for your workspace, scoped to contacts:manage. Pass it as a Bearer token in the Authorization header.

Remove a contact from a list
curl https://api.mailcraft.host/v1/contacts/01j9x2h6w9q3b6xk0m2v8r5tzn/lists/4 \
  -X DELETE \
  -H 'Authorization: Bearer sk_live_...'
(empty body)