Rate limits
Limits are per API key:
Exceeding a limit returns
429 rate_limited with a Retry-After header (seconds):
Retry-After rather than guessing your own backoff; it reflects the actual window. These limits are sized for steady-state integrations (a nightly full-roster sync for hundreds of employers fits comfortably); if a bulk migration needs more, ask your partner engineer for a temporary raise rather than building a throttle dance.
Failed authentication is throttled separately: requests with a missing, malformed, revoked, or unknown API key are limited to 30 attempts per minute per source IP, after which the API returns 429 rate_limited instead of 401. Authenticated traffic is unaffected by this limiter. If you see it during development, check that your key is loaded correctly rather than retrying.
Idempotency
These endpoints accept anIdempotency-Key header:
Other writes ignore the header:
PATCH /groups/{groupId},
PATCH /groups/{groupId}/members/{memberId}, POST /embed-sessions (mint a
fresh session on every open anyway), POST /webhook/test, and
POST /events/{eventId}/redeliver.
- 24-hour replay window. Repeating the same key with the same body within
24 hours returns the stored response (same status and body) without
re-executing anything. Replays carry an
Idempotent-Replay: trueheader. - Scoped to the key, the body, the endpoint, and the mode. A replay needs the same key, the same JSON body, the same method and path, and a key of the same mode. The same key with a different body runs as a new request.
- Only successful responses are stored. Errors returned before or during
the write (validation failures,
409,410,5xx) are not stored, so a corrected retry runs normally under the same key. APUT /censusresponse that reports per-row errors is a200and is stored. - Replays of
PUT /webhookreturn the stored body, including the signing secret from the original call. A new key rotates the secret. - Key is free-form. Any non-empty string. Deterministic keys derived from
your own entity IDs (
enroll-{companyId}-{quoteId}) work better than random UUIDs, because retries after a process crash regenerate the same key. - Scoped to your partner account. No cross-partner collisions.
POST /groups and POST /enrollments. A timeout is not a failure; the request
may have landed. With an idempotency key, the retry answers that question
safely.