Developers
The API, generated from the code that runs it
A cursor-paged REST API over contacts, lists, tags, segments, campaigns and automations.
https://mintmailer.app/api/v1Every path is relative to it, so /contacts is https://mintmailer.app/api/v1/contacts.Getting started
Authentication. Send your key as Authorization: Bearer rvz_live_…. A key belongs to one organisation and carries a fixed set of scopes, chosen when it was created; every operation states the scope it requires. A key without the scope gets 403, and a request for another organisation's row gets 404 rather than 403 — confirming that an id exists elsewhere is itself a disclosure.
Pagination. List endpoints return {data, has_more, next_cursor}. Pass next_cursor back as cursor to walk forward; the default page is 50 rows and the maximum is 100. The cursor is a keyset, not an offset, so a row inserted while you page cannot cause a skip or a repeat — which is what makes an incremental sync safe. It is opaque: pass it back unmodified and do not parse it.
Idempotency. Send an Idempotency-Key header on any write and a retry of that exact request returns the first response byte for byte, including its status and any id, rather than creating a second row. Idempotent-Replay on the response says which of the two happened. Omitting the header is allowed and gives you ordinary at-least-once semantics.
Rate limits. Per key, not per organisation, so one integration cannot spend another's budget. RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset are on every response, so you never have to exceed the limit to discover it.
Versioning. v1 changes additively only: an endpoint, an optional field or a new enum value may appear at any time, and nothing is ever removed, renamed or retyped inside a major version. Parse leniently and a release cannot break you. No version is withdrawn on less than twelve months' notice, announced with a Sunset header on every affected response long before it stops answering.
Automations
/automationsautomation:viewList automations
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
status | "draft" | "active" | "paused" | "archived" | "draft" | "active" | "paused" | "archived"[] |
200 page of Automation in dataErrors: 400, 401, 403, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "automation",
"name": "Weekly digest",
"status": "draft",
"version": 1,
"allow_reentry": true,
"definition": {
"version": 1,
"entryNodeId": "entryNodeId",
"nodes": {}
},
"activated_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}/automations/{id}automation:viewRetrieve an automation
Path parameters
idrequired | string | The automation's id. |
200 Automation in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "automation",
"name": "Weekly digest",
"status": "draft",
"version": 1,
"allow_reentry": true,
"definition": {
"version": 1,
"entryNodeId": "entryNodeId",
"nodes": {}
},
"activated_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/automations/{id}/activateautomation:editTurn an automation on, or resume a paused one
Path parameters
idrequired | string | The automation's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
200 Automation in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "automation",
"name": "Weekly digest",
"status": "draft",
"version": 1,
"allow_reentry": true,
"definition": {
"version": 1,
"entryNodeId": "entryNodeId",
"nodes": {}
},
"activated_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/automations/{id}/enrollautomation:editEnrol contacts into an active automation
Path parameters
idrequired | string | The automation's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
contact_idsrequired | string[] |
200 Enrollment in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"object": "enrollment",
"requested": 128,
"enrolled": 128
}
}/automations/{id}/pauseautomation:editPause an automation, holding everyone inside it
Path parameters
idrequired | string | The automation's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
200 Automation in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "automation",
"name": "Weekly digest",
"status": "draft",
"version": 1,
"allow_reentry": true,
"definition": {
"version": 1,
"entryNodeId": "entryNodeId",
"nodes": {}
},
"activated_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}Campaigns
/campaignscampaign:viewList campaigns
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
status | "draft" | "scheduled" | "dispatching" | "sending" | "testing" | "paused" | "sent" | "cancelled" | "failed" | "draft" | "scheduled" | "dispatching" | "sending" | "testing" | "paused" | "sent" | "cancelled" | "failed"[] |
200 page of Campaign in dataErrors: 400, 401, 403, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "campaign",
"name": "Weekly digest",
"status": "draft",
"subject": "Your July statement",
"preheader": "Everything that moved this month, in one place.",
"sender_identity_id": "cly3k9f2b0000q8n1h4d7g5xz",
"from_name": "Acme",
"from_email": "[email protected]",
"reply_to": "[email protected]",
"email_document_id": "cly3k9f2b0000q8n1h4d7g5xz",
"audience": {
"include": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
},
"exclude": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
}
},
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2026-07-14T09:31:02.000Z",
"send_started_at": "2026-07-14T09:31:02.000Z",
"send_completed_at": "2026-07-14T09:31:02.000Z",
"recipient_count": 128,
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}/campaignscampaign:editCreate a campaign
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
namerequired | string |
201 Campaign in dataErrors: 400, 401, 403, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "campaign",
"name": "Weekly digest",
"status": "draft",
"subject": "Your July statement",
"preheader": "Everything that moved this month, in one place.",
"sender_identity_id": "cly3k9f2b0000q8n1h4d7g5xz",
"from_name": "Acme",
"from_email": "[email protected]",
"reply_to": "[email protected]",
"email_document_id": "cly3k9f2b0000q8n1h4d7g5xz",
"audience": {
"include": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
},
"exclude": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
}
},
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2026-07-14T09:31:02.000Z",
"send_started_at": "2026-07-14T09:31:02.000Z",
"send_completed_at": "2026-07-14T09:31:02.000Z",
"recipient_count": 128,
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/campaigns/{id}campaign:viewRetrieve a campaign
Path parameters
idrequired | string | The campaign's id. |
200 Campaign in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "campaign",
"name": "Weekly digest",
"status": "draft",
"subject": "Your July statement",
"preheader": "Everything that moved this month, in one place.",
"sender_identity_id": "cly3k9f2b0000q8n1h4d7g5xz",
"from_name": "Acme",
"from_email": "[email protected]",
"reply_to": "[email protected]",
"email_document_id": "cly3k9f2b0000q8n1h4d7g5xz",
"audience": {
"include": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
},
"exclude": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
}
},
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2026-07-14T09:31:02.000Z",
"send_started_at": "2026-07-14T09:31:02.000Z",
"send_completed_at": "2026-07-14T09:31:02.000Z",
"recipient_count": 128,
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/campaigns/{id}campaign:editUpdate a draft campaign
Path parameters
idrequired | string | The campaign's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
name | string | |
subject | string | null | |
preheader | string | null | |
sender_identity_id | string | |
reply_to | "" | string | null | |
email_document_id | string | |
audience | object | |
include | object | |
exclude | object | |
track_opens | boolean | |
track_clicks | boolean |
200 Campaign in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "campaign",
"name": "Weekly digest",
"status": "draft",
"subject": "Your July statement",
"preheader": "Everything that moved this month, in one place.",
"sender_identity_id": "cly3k9f2b0000q8n1h4d7g5xz",
"from_name": "Acme",
"from_email": "[email protected]",
"reply_to": "[email protected]",
"email_document_id": "cly3k9f2b0000q8n1h4d7g5xz",
"audience": {
"include": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
},
"exclude": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
}
},
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2026-07-14T09:31:02.000Z",
"send_started_at": "2026-07-14T09:31:02.000Z",
"send_completed_at": "2026-07-14T09:31:02.000Z",
"recipient_count": 128,
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/campaigns/{id}campaign:deleteDelete a draft or cancelled campaign
Path parameters
idrequired | string | The campaign's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
204 no bodyErrors: 400, 401, 403, 404, 409, 422, 429, 500/campaigns/{id}/cancelcampaign:sendCancel a scheduled or sending campaign
Path parameters
idrequired | string | The campaign's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
200 Campaign in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "campaign",
"name": "Weekly digest",
"status": "draft",
"subject": "Your July statement",
"preheader": "Everything that moved this month, in one place.",
"sender_identity_id": "cly3k9f2b0000q8n1h4d7g5xz",
"from_name": "Acme",
"from_email": "[email protected]",
"reply_to": "[email protected]",
"email_document_id": "cly3k9f2b0000q8n1h4d7g5xz",
"audience": {
"include": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
},
"exclude": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
}
},
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2026-07-14T09:31:02.000Z",
"send_started_at": "2026-07-14T09:31:02.000Z",
"send_completed_at": "2026-07-14T09:31:02.000Z",
"recipient_count": 128,
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/campaigns/{id}/schedulecampaign:sendSchedule a campaign, or send it now
Path parameters
idrequired | string | The campaign's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
scheduled_at | string | When to send, as an ISO 8601 instant. Omit to send now. |
200 Campaign in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "campaign",
"name": "Weekly digest",
"status": "draft",
"subject": "Your July statement",
"preheader": "Everything that moved this month, in one place.",
"sender_identity_id": "cly3k9f2b0000q8n1h4d7g5xz",
"from_name": "Acme",
"from_email": "[email protected]",
"reply_to": "[email protected]",
"email_document_id": "cly3k9f2b0000q8n1h4d7g5xz",
"audience": {
"include": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
},
"exclude": {
"list_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"tag_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
],
"segment_ids": [
"cly3k9f2b0000q8n1h4d7g5xz"
]
}
},
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2026-07-14T09:31:02.000Z",
"send_started_at": "2026-07-14T09:31:02.000Z",
"send_completed_at": "2026-07-14T09:31:02.000Z",
"recipient_count": 128,
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/campaigns/{id}/statsanalytics:viewRetrieve a campaign's engagement totals and rates
Path parameters
idrequired | string | The campaign's id. |
200 CampaignStats in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": {
"object": "campaign_stats",
"campaign_id": "cly3k9f2b0000q8n1h4d7g5xz",
"sent": 128,
"delivered": 128,
"opened": 128,
"unique_opened": 128,
"clicked": 128,
"unique_clicked": 128,
"bounced": 128,
"soft_bounced": 128,
"complained": 128,
"unsubscribed": 128,
"failed": 128,
"open_rate": 0.42,
"click_rate": 0.42,
"click_to_open_rate": 0.42,
"bounce_rate": 0.42,
"hard_bounce_rate": 0.42,
"complaint_rate": 0.42,
"unsubscribe_rate": 0.42,
"updated_at": "2026-07-14T09:31:02.000Z"
}
}Contacts
/contactscontact:viewList contacts
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
status | "subscribed" | "unsubscribed" | "bounced" | "complained" | "pending" | "subscribed" | "unsubscribed" | "bounced" | "complained" | "pending"[] | |
list_id | string | string[] | |
tag_id | string | string[] | |
search | string |
200 page of Contact in dataErrors: 400, 401, 403, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "contact",
"email": "[email protected]",
"first_name": "Jamie",
"last_name": "Rivera",
"status": "subscribed",
"custom_fields": {
"plan": "Pro",
"signup_source": "webinar"
},
"opt_in_source": "signup_form",
"opt_in_at": "2026-07-14T09:31:02.000Z",
"last_engaged_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}/contactscontact:editCreate or update a contact
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
emailrequired | string | |
first_name | string | null | |
last_name | string | null | |
opt_in_source | string | null | |
status | "subscribed" | "unsubscribed" | "bounced" | "complained" | "pending" |
200 or 201 Contact in dataErrors: 400, 401, 403, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "contact",
"email": "[email protected]",
"first_name": "Jamie",
"last_name": "Rivera",
"status": "subscribed",
"custom_fields": {
"plan": "Pro",
"signup_source": "webinar"
},
"opt_in_source": "signup_form",
"opt_in_at": "2026-07-14T09:31:02.000Z",
"last_engaged_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/contacts/{id}contact:viewRetrieve a contact
Path parameters
idrequired | string | The contact's id. |
200 Contact in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "contact",
"email": "[email protected]",
"first_name": "Jamie",
"last_name": "Rivera",
"status": "subscribed",
"custom_fields": {
"plan": "Pro",
"signup_source": "webinar"
},
"opt_in_source": "signup_form",
"opt_in_at": "2026-07-14T09:31:02.000Z",
"last_engaged_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/contacts/{id}contact:editUpdate a contact
Path parameters
idrequired | string | The contact's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
email | string | |
first_name | string | null | |
last_name | string | null | |
opt_in_source | string | null | |
status | "subscribed" | "unsubscribed" | "bounced" | "complained" | "pending" |
200 Contact in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "contact",
"email": "[email protected]",
"first_name": "Jamie",
"last_name": "Rivera",
"status": "subscribed",
"custom_fields": {
"plan": "Pro",
"signup_source": "webinar"
},
"opt_in_source": "signup_form",
"opt_in_at": "2026-07-14T09:31:02.000Z",
"last_engaged_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/contacts/{id}contact:deleteDelete a contact
Path parameters
idrequired | string | The contact's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
204 no bodyErrors: 400, 401, 403, 404, 409, 422, 429, 500/contacts/{id}/listslist:viewList the lists a contact belongs to
Path parameters
idrequired | string | The contact's id. |
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
200 page of List in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "list",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}Custom fields
/custom_fieldscontact:viewList the organisation's custom field definitions
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
200 page of CustomField in dataErrors: 400, 401, 403, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "custom_field",
"key": "plan",
"label": "Plan",
"type": "text",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}Lists
/listslist:viewList contact lists
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
name | string |
200 page of List in dataErrors: 400, 401, 403, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "list",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}/listslist:editCreate a contact list
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
namerequired | string | |
description | string | null |
201 List in dataErrors: 400, 401, 403, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "list",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/lists/{id}list:viewRetrieve a contact list
Path parameters
idrequired | string | The list's id. |
200 List in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "list",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/lists/{id}list:editUpdate a contact list
Path parameters
idrequired | string | The list's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
name | string | |
description | string | null |
200 List in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "list",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/lists/{id}list:editDelete a contact list, keeping its contacts
Path parameters
idrequired | string | The list's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
204 no bodyErrors: 400, 401, 403, 404, 409, 422, 429, 500/lists/{id}/contactscontact:viewList the contacts on a list
Path parameters
idrequired | string | The list's id. |
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
200 page of Contact in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "contact",
"email": "[email protected]",
"first_name": "Jamie",
"last_name": "Rivera",
"status": "subscribed",
"custom_fields": {
"plan": "Pro",
"signup_source": "webinar"
},
"opt_in_source": "signup_form",
"opt_in_at": "2026-07-14T09:31:02.000Z",
"last_engaged_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}/lists/{id}/contactslist:editAdd contacts to a list
Path parameters
idrequired | string | The list's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
contact_idsrequired | string[] |
200 MembershipChange in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"object": "membership_change",
"changed": 128
}
}/lists/{id}/contactslist:editRemove contacts from a list
Path parameters
idrequired | string | The list's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
contact_idsrequired | string[] |
200 MembershipChange in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"object": "membership_change",
"changed": 128
}
}Segments
/segmentssegment:viewList segments
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
name | string |
200 page of Segment in dataErrors: 400, 401, 403, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "segment",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"rules": {
"version": 1,
"match": "all",
"groups": [
"groups"
]
},
"last_count": 128,
"last_counted_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}/segmentssegment:editCreate a segment
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
namerequired | string | |
description | string | null | |
rulesrequired | any |
201 Segment in dataErrors: 400, 401, 403, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "segment",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"rules": {
"version": 1,
"match": "all",
"groups": [
"groups"
]
},
"last_count": 128,
"last_counted_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/segments/{id}segment:viewRetrieve a segment
Path parameters
idrequired | string | The segment's id. |
200 Segment in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "segment",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"rules": {
"version": 1,
"match": "all",
"groups": [
"groups"
]
},
"last_count": 128,
"last_counted_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/segments/{id}segment:editUpdate a segment
Path parameters
idrequired | string | The segment's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
Request body
name | string | |
description | string | null | |
rules | any |
200 Segment in dataErrors: 400, 401, 403, 404, 409, 422, 429, 500Example response
{
"data": {
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "segment",
"name": "Weekly digest",
"description": "Everyone who opened something in the last 90 days.",
"rules": {
"version": 1,
"match": "all",
"groups": [
"groups"
]
},
"last_count": 128,
"last_counted_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
}/segments/{id}segment:editDelete a segment
Path parameters
idrequired | string | The segment's id. |
Headers
Idempotency-Key | string | A unique string of your choosing. Retrying a request with the same key returns the first response byte for byte — same status, same ids — instead of doing the work twice. Scoped to this key, this method and this path. |
204 no bodyErrors: 400, 401, 403, 404, 409, 422, 429, 500/segments/{id}/contactscontact:viewList the contacts a segment selects
Path parameters
idrequired | string | The segment's id. |
Query parameters
cursor | string | next_cursor from the previous page, passed back unmodified. |
limit | integer | Rows per page, 1–100. Defaults to 50. |
200 page of Contact in dataErrors: 400, 401, 403, 404, 429, 500Example response
{
"data": [
{
"id": "cly3k9f2b0000q8n1h4d7g5xz",
"object": "contact",
"email": "[email protected]",
"first_name": "Jamie",
"last_name": "Rivera",
"status": "subscribed",
"custom_fields": {
"plan": "Pro",
"signup_source": "webinar"
},
"opt_in_source": "signup_form",
"opt_in_at": "2026-07-14T09:31:02.000Z",
"last_engaged_at": "2026-07-14T09:31:02.000Z",
"created_at": "2026-07-14T09:31:02.000Z",
"updated_at": "2026-07-14T09:31:02.000Z"
}
],
"has_more": false,
"next_cursor": null
}Object reference
Every resource carries an object field naming its type, so a client holding one response can tell what it has without inferring from the shape.
Automation
Fields
idrequired | string | |
objectrequired | "automation" | |
namerequired | string | |
statusrequired | "draft" | "active" | "paused" | "archived" | |
versionrequired | integer | |
allow_reentryrequired | boolean | |
definitionrequired | object | The flow, in the grammar automationDefinitionSchema defines. Read-only in v1. |
versionrequired | integer | |
entryNodeIdrequired | string | null | |
nodesrequired | object | |
activated_atrequired | string | null | |
created_atrequired | string | |
updated_atrequired | string |
Campaign
Fields
idrequired | string | |
objectrequired | "campaign" | |
namerequired | string | |
statusrequired | "draft" | "scheduled" | "dispatching" | "sending" | "testing" | "paused" | "sent" | "cancelled" | "failed" | |
subjectrequired | string | null | |
preheaderrequired | string | null | |
sender_identity_idrequired | string | null | |
from_namerequired | string | null | |
from_emailrequired | string | null | |
reply_torequired | string | null | |
email_document_idrequired | string | null | |
audiencerequired | object | |
includerequired | object | |
excluderequired | object | |
track_opensrequired | boolean | |
track_clicksrequired | boolean | |
scheduled_atrequired | string | null | |
send_started_atrequired | string | null | |
send_completed_atrequired | string | null | |
recipient_countrequired | integer | |
created_atrequired | string | |
updated_atrequired | string |
CampaignStats
Fields
objectrequired | "campaign_stats" | |
campaign_idrequired | string | |
sentrequired | integer | |
deliveredrequired | integer | |
openedrequired | integer | |
unique_openedrequired | integer | |
clickedrequired | integer | |
unique_clickedrequired | integer | |
bouncedrequired | integer | |
soft_bouncedrequired | integer | |
complainedrequired | integer | |
unsubscribedrequired | integer | |
failedrequired | integer | |
open_raterequired | number | null | |
click_raterequired | number | null | |
click_to_open_raterequired | number | null | |
bounce_raterequired | number | null | |
hard_bounce_raterequired | number | null | |
complaint_raterequired | number | null | |
unsubscribe_raterequired | number | null | |
updated_atrequired | string | null |
Contact
Fields
idrequired | string | |
objectrequired | "contact" | |
emailrequired | string | |
first_namerequired | string | null | |
last_namerequired | string | null | |
statusrequired | "subscribed" | "unsubscribed" | "bounced" | "complained" | "pending" | |
custom_fieldsrequired | object | |
opt_in_sourcerequired | string | null | |
opt_in_atrequired | string | null | |
last_engaged_atrequired | string | null | |
created_atrequired | string | |
updated_atrequired | string |
CustomField
Fields
idrequired | string | |
objectrequired | "custom_field" | |
keyrequired | string | |
labelrequired | string | |
typerequired | "text" | "number" | "date" | "boolean" | |
created_atrequired | string | |
updated_atrequired | string |
Enrollment
Fields
objectrequired | "enrollment" | |
requestedrequired | integer | |
enrolledrequired | integer |
Error
Every 4xx and 5xx response has this shape, whatever went wrong.
Fields
errorrequired | object | |
typerequired | "invalid_request_error" | "authentication_error" | "permission_error" | "rate_limit_error" | "idempotency_error" | "api_error" | The coarse class. Switch on this, not on code. |
coderequired | "parameter_invalid" | "parameter_missing" | "malformed_request" | "api_key_missing" | "api_key_invalid" | "api_key_revoked" | "api_key_expired" | "insufficient_scope" | "resource_missing" | "resource_conflict" | "idempotency_key_in_flight" | "unprocessable" | "rate_limit_exceeded" | "internal_error" | The specific reason, for a human and for a log. |
messagerequired | string | |
param | string | The offending field, as a dotted path. Present when one field is at fault. |
request_idrequired | string | Also returned in X-Request-Id. Quote it in a support message and we can find exactly this request. |
List
Fields
idrequired | string | |
objectrequired | "list" | |
namerequired | string | |
descriptionrequired | string | null | |
created_atrequired | string | |
updated_atrequired | string |
MembershipChange
Fields
objectrequired | "membership_change" | |
changedrequired | integer |
Segment
Fields
idrequired | string | |
objectrequired | "segment" | |
namerequired | string | |
descriptionrequired | string | null | |
rulesrequired | object | The saved rule tree, in the grammar segmentRulesSchema defines. Pass it back unchanged to leave it alone. |
versionrequired | integer | |
matchrequired | "all" | "any" | |
groupsrequired | any[] | |
last_countrequired | integer | null | |
last_counted_atrequired | string | null | |
created_atrequired | string | |
updated_atrequired | string |
Tag
Fields
idrequired | string | |
objectrequired | "tag" | |
namerequired | string | |
colorrequired | "neutral" | "positive" | "warning" | "danger" | "info" | |
created_atrequired | string | |
updated_atrequired | string |
Everything here is generated from the schemas the API actually validates against. The machine-readable form is at /api/v1/openapi.json.