Limits and best practices
Requests per minute
| Limit | Value |
|---|---|
| Per API key | 600 requests per minute (fixed window) |
| Response when exceeded | 429 API_KEY_RATE_LIMITED |
When you receive a 429, wait and retry with exponential backoff (1 s, 2 s, 4 s…) plus a little jitter. The X-RateLimit-* headers will arrive in the next version; until then, measure your own rate.
Sizes
| Operation | Maximum |
|---|---|
POST /contacts/bulk |
500 ids per call, 20 tags |
POST /campaigns/{id}/recipients by ids |
20,000 ids per call |
| Tags per contact | 50, up to 60 characters each |
| Contact note | 4,000 characters |
Page size (pageSize) |
100 (default 20) |
Idempotency
Creating the same contact twice doesn't duplicate it: the second call responds 409 CONTACT_PHONE_EXISTS with the existing contactId. Sending a campaign twice responds 400 ("already sent"). Adding the same audience twice doesn't duplicate recipients (alreadyIn counts them). For every other operation, store the id we return and don't repeat the creation if the response was lost; the Idempotency-Key header will arrive in the next version.
Timing
Respond to your webhooks in under 10 seconds (an immediate 200 is enough; process afterwards). API requests usually take under 300 ms; set a 30 s timeout in your client.
Dates and time zones
All dates are ISO 8601 with time zone (2026-10-14T10:21:00.000Z). When scheduling a campaign, include the time zone in the date (2026-10-20T09:00:00+02:00).
Stability
- The API is versioned in the path (
/api/v1). We add fields without notice; we never remove or rename fields within the same version. - Changes are published in the changelog; deprecations are announced 6 months in advance.
- Treat enumeration values (
status,source,channelType) as open lists: new values may appear.