Skip to main content

Error Codes

There are two kinds of errors: request-level errors, which stop the entire request before any contact is processed, and per-contact errors, which describe one contact's outcome. How a per-contact error surfaces depends on which endpoint you called — see Create or Update a Contact or Sync a Contact Batch for the full explanation.

Request-level errors

These prevent the whole request from being processed at all — nothing gets written.

HTTP statusCodeMeaningApplies to
400INVALID_REQUESTAn array was sent to /contacts, a bare object was sent to /contacts/batch, the array is empty, or the body is otherwise invalidAll endpoints
400BATCH_LIMIT_EXCEEDEDMore than 50 contacts were sent in one request/contacts/batch only
401INVALID_API_KEYThe API key is missing, invalid, expired, or revokedAll endpoints
413PAYLOAD_TOO_LARGEThe request body is larger than 1 MBAll endpoints
429RATE_LIMIT_EXCEEDEDYou've exceeded 300 requests/minute for your organization (shared across every endpoint) — see Rate LimitsAll endpoints
500INTERNAL_ERRORSomething went wrong on our endAll endpoints

A request-level error looks like this:

{
"request_id": "req_01J7X8W3E4N8",
"error": {
"code": "INVALID_API_KEY",
"message": "The supplied API key is invalid"
}
}

Per-contact errors

The same codes apply on both endpoints, but they surface differently — see the HTTP status on /contacts column, which only means something on the single-contact endpoint:

CodeMeaningHTTP status on /contacts
INVALID_EMAILThe email address isn't valid, even after trimming and lowercasing400
DUPLICATE_EMAILThe contact already exists and overwrite wasn't set to true409
SUPPRESSED_EMAILThe contact is suppressed (bounced/complained/unsubscribed) and overwrite wasn't set to true409
EMPTY_LIST_IDSNo list ID was provided400
TOO_MANY_LIST_IDSMore than 20 list IDs were provided400
INVALID_LISTOne or more list IDs don't exist, are archived, or belong to a different organization — the response includes which ones under invalidListIds400
UNKNOWN_FIELDA key in fields doesn't match any standard field or existing custom field — check for typos, or define the field first in Settings → Custom Fields400
FIELD_TYPE_MISMATCHA value doesn't match its field's configured type (e.g. text sent for a number field)400
REQUIRED_FIELD_MISSINGA required custom field has no value and no configured default — or you tried to clear one with null, which is never allowed400
DUPLICATE_IN_REQUESTThe same normalized email appeared more than once in the same batch. Duplicate rows aren't merged automatically — send each email only once per requestn/a — only possible on /contacts/batch, since it requires two rows

On POST /api/v2/contacts/batch, a per-contact error appears inside results, alongside any contacts that succeeded, under an overall 200:

{
"email": "not-an-email",
"status": "failed",
"code": "INVALID_EMAIL",
"message": "Enter a valid email address"
}

On POST /api/v2/contacts, the same shape is the entire response body — no results wrapper — and the HTTP status matches the table above:

HTTP 409
{
"request_id": "req_...",
"email": "alex@example.com",
"status": "failed",
"code": "DUPLICATE_EMAIL",
"message": "A customer with this email already exists"
}

INVALID_LIST also includes the specific offending IDs, on either endpoint:

{
"email": "alex@example.com",
"status": "failed",
"code": "INVALID_LIST",
"message": "One or more lists were not found in this organization",
"invalidListIds": ["000000000000000000000000"]
}

What's next