API reference
Errors
The error body, HTTP status codes and the error codes the API returns.
Every failure uses the same JSON body, so you can parse errors without checking the endpoint.
{
"error": {
"code": "validation_failed",
"message": "invalid request",
"details": [{ "field": "name", "reason": "is required" }],
"request_id": "01JABCDEF0123456789XYZ"
}
}
code is stable and meant for programs, message is for people, details lists field-level problems when there are any, and request_id matches the X-Request-Id response header. Quote it when you contact support. Server errors never leak internals: an unexpected failure is logged with the request id and returned as a generic 500.
Status and codes
| Status | code | When |
|---|---|---|
| 400 | validation_failed | Malformed body or parameters (for example a bad page, an unknown filter field or operator). |
| 400 | invalid_token | A one-time token (invitation, reset) is wrong or used. |
| 401 | unauthorized | Missing, invalid or expired credentials; session timed out. |
| 401 | invalid_signature | A signed provider callback failed verification. |
| 403 | forbidden | The key or role lacks permission, or the IP is not allow-listed. |
| 403 | mfa_enrollment_required, sso_required, maker_checker | Policy blocks the call; see authentication. |
| 404 | not_found | No such resource in your tenant. Resources of other tenants are indistinguishable from missing ones. |
| 405 | method_not_allowed | The path exists but not for this method. |
| 409 | conflict, immutable, stale_version, run_in_progress | Duplicate unique value, an immutable field, an outdated version, or a job already running. |
| 413 | payload_too_large | Upload over the limit. |
| 422 | validation_failed | Well-formed but semantically invalid (for example a macro that does not exist, no tracking domain for a link). Also provider_invalid, no_tracking_domain. |
| 423 | account_locked | Too many failed logins. |
| 429 | rate_limited | Per-key token bucket empty. Honour Retry-After. |
| 502 | provider_error, idp_error, upstream_error, upstream_unavailable | A downstream provider, identity provider or internal service failed. Safe to retry. |
| 503 | storage_unavailable, unavailable | A dependency is down. Retry with backoff. |
Retrying safely
GET,PUTandDELETEare idempotent by design; retry them on429,502and503.- The contract reserves an
Idempotency-Keyheader forPOST, but the API does not de-duplicate on it today. For creates that must not duplicate, store your own reference inexternal_refand look it up withfilter[external_ref]=...before creating. - Conversions are the exception: the ingest endpoints de-duplicate on
txn_idper goal, so resending a conversion is safe. See deduplication.
Tracking endpoints answer differently
Postbacks and pixels on the ingest host never return 4xx or 5xx for business outcomes. They answer 200 with {"status": "created|duplicate|rejected|unmatched|updated", "conversion_id", "reason"} because advertisers' servers retry on errors. See conversion tracking methods.