Errors, rate limits and retries
Status codes, the error format, request limits and safe retries with idempotency keys.
Status codes
| Code | Meaning |
|---|---|
200 | Success |
201 | Created — a click, impression or conversion was recorded |
400 | A required value is missing or invalid |
401 | No API key, or the key is wrong, revoked or its account is inactive |
403 | The key is valid but can't do this — e.g. a non-admin key on an admin endpoint, a write with a read-only key, or a campaign you can't access |
404 | The endpoint or record doesn't exist |
409 | An earlier request with the same Idempotency-Key is still running |
422 | The request can't be processed — e.g. the click was rejected as fraud, or an Idempotency-Key was reused for a different request |
429 | Too many requests, or a campaign cap was reached |
5xx | Something went wrong on our side — safe to retry |
Error format
{
"success": false,
"message": "API key required. Send Authorization: Bearer <api_key> or x-api-key.",
"error": "API key required. Send Authorization: Bearer <api_key> or x-api-key."
}Some errors add detail fields — for example role on a permission error, or caps when a campaign cap is reached.
Rate limits
Each key can make up to 600 requests per minute. Requests without a key are limited to 120 per minute.
Every response tells you where you stand:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 42X-RateLimit-Reset is the number of seconds until the limit resets. Over the limit, you'll get 429 with a Retry-After header — wait that many seconds before trying again.
Safe retries with idempotency keys
If a POST, PATCH or DELETE times out, you can't tell whether it went through. Add an Idempotency-Key header so a retry can never create a duplicate:
POST /api/v1/conversions
Idempotency-Key: 5f2b8c1e-9a44-4c3d-b1e7-2c9d4e6a8f30Use a new unique value (a UUID is ideal, up to 255 characters) for each operation, and the same value when you retry it.
| Situation | What happens |
|---|---|
| First request with the key | Runs normally; the response is remembered for 24 hours |
| Retry after it finished | The original response is returned again, with Idempotent-Replay: true |
| Retry while the first is still running | 409 — wait and retry |
| Same key, different request body | 422 |
The first attempt failed with a 5xx | The key is released, so the retry runs for real |
Keys are scoped to your API key, so they can't collide with another account's.