Skip to content

API keys, responses and limits

Every call to the public API carries an API key. All routes start with https://dashboard.azimea.com/api/v1; the API reference lists each one.

Owners and admins make keys in Settings › API keys:

  1. Give the key a name you will recognise later (2–100 characters), such as the system that will use it.
  2. Tick only the permissions that system needs (below).
  3. Choose when it expires: in 30, 90 or 365 days, or never (chosen explicitly).
  4. Copy the key. It is shown once; afterwards the list shows only its ends (azm_live_7f3c…5e0c) and when it was last used.

A company can have up to 10 active keys. A key stops working the moment it is revoked or expires; Azimea answers the same way for a revoked key as for one that never existed.

Permission What it allows
contacts:read Read contacts, segments, topics and contact fields: GET /contacts, GET /contacts/{reference}, GET /segments, GET /topics, GET /contact-attributes
contacts:write Create and update contacts and contact fields: POST /contacts, POST /contacts/batch, POST /contact-attributes, PATCH /contact-attributes/{key}
contacts:erase Erase a contact for good (GDPR): DELETE /contacts/{reference}. Not included in any other permission
events:write Report what people did in your product: POST /events
emails:send Send transactional email: POST /sending/emails
items:read Read a catalogue item you sent: GET /items/{externalId}
items:write Write your catalogue: POST /items, POST /items/batch, DELETE /items/{externalId}
orders:read Read orders: GET /commerce/orders

A call the key has no permission for is answered 403.

Keys made inside a sandbox start with azm_test_. They work exactly like live keys, against the sandbox’s own data. No email sent from a sandbox reaches anyone: it lands in the sandbox’s inbox, and its delivery webhooks are still sent, so the whole integration can be tried end to end.

Put it in the Authorization header as a bearer token, on every call:

Terminal window
curl https://dashboard.azimea.com/api/v1/segments \
-H "Authorization: Bearer $AZIMEA_API_KEY"

Keep keys on your server. A key in a browser, a mobile app or a public repository can be used by anyone who finds it: revoke it and make a new one.

Every answer from the API has the same envelope:

{
"isSuccess": false,
"value": null,
"status": 5,
"errors": [{ "code": "audience.contact_email_required", "message": "An email address is needed to create a new contact.", "params": null }],
"fieldErrors": {
"email": [{ "code": "audience.contact_email_required", "message": "An email address is needed to create a new contact.", "params": null }]
}
}
  • isSuccess and the HTTP status say whether it worked. value holds the result when it did.
  • errors lists what went wrong. Each error has a code — stable, meant for your code — and an English message for logs; params carries the numbers in the message (a minimum, a maximum) when there are any. Every code is in the error codes catalog.
  • fieldErrors groups validation errors by the request field that caused them.
  • status is an internal result number; rely on the HTTP status instead.
HTTP status Meaning
200 / 201 Done; value holds the result
400 The request is not valid: see errors[].code and fieldErrors
401 No key, an unknown or revoked key, or an expired one
403 The key lacks the permission this call needs
404 What you asked for does not exist in your account
409 It conflicts with what exists (for example, a contact field with that key already exists)
429 Too many calls for this key (below)
503 Azimea cannot answer right now; try again later

401, 403 and 429 are answered before the call reaches Azimea’s logic: rely on the status code, not on a body.

Each key may make 600 calls per minute, counted together across every public endpoint, in fixed one-minute windows. Two systems with two keys never share a limit. A batch call (POST /contacts/batch, POST /items/batch, POST /events with up to 100 events) counts as one call, so batches are the way to move volume.

Past the limit, the answer is 429 Too Many Requests with a Retry-After header: the number of seconds to wait before the next call is allowed.

Retry on a network error, a timeout, 429 (after Retry-After) or 503. Do not retry a 400, 401, 403 or 404 unchanged: the same request gets the same answer. Whether a retry is safe depends on the call:

Call Safe to retry?
POST /events Yes. An event’s id is yours and unique in your account: a second delivery is counted as a duplicate, not recorded twice.
POST /contacts, POST /contacts/batch Yes. They create or update the same contact (by id, then external id, then email).
POST /items, POST /items/batch Yes. They create or update the item with that externalId.
PATCH /contact-attributes/{key}, DELETE /items/{externalId} Yes. Doing it twice ends in the same state.
POST /contact-attributes Yes: the second call is refused with 409, because the field already exists.
POST /sending/emails Only with an Idempotency-Key header. With it, a second call with the same key returns the first message and sends nothing more. Without it, each call queues a new email, and a retry after a timeout can send the person the same email twice. See send your first email.
GET calls Yes.