Skip to main content

Rate limits

Limits are per API key: Exceeding a limit returns 429 rate_limited with a Retry-After header (seconds):
Honor 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 an Idempotency-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.
Semantics:
  • 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: true header.
  • 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. A PUT /census response that reports per-row errors is a 200 and is stored.
  • Replays of PUT /webhook return 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.
Use it on every call that creates something an employer will see, especially 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.