Skip to main content

Status codes

Errors carry a human-readable detail:

409 names the state, not the mistake

The request was well-formed and the world was not ready for it. The body carries a code you can branch on. 422 outside_customer_service_window is the one to design around: WhatsApp permits free-form messages only within 24 hours of the customer’s last inbound message. The error carries the window object, so you can show a countdown rather than discovering the limit by failing. Send an approved template instead.

404 is deliberately ambiguous

A tenant that belongs to another partner and a tenant that does not exist both return 404. A 403 would confirm the id is real, which would let anyone enumerate a competitor’s customer list one guess at a time. Do not infer existence from the status code.

Retries and idempotency

Tenant provisioning is idempotent on (you, external_ref) — retry it freely after a timeout. Knowledge sync is a full replace, so re-sending the same set converges rather than duplicating. For everything else, retry 429 and 5xx with exponential backoff. Do not auto-retry a 400.

Async work

Document upload and website crawl return before the work is done. Poll the job before telling a merchant their knowledge is ready.

Versioning

The surface is /api/v1/. Additive changes — new optional fields, new endpoints — can arrive without notice, so parse defensively and ignore fields you do not recognise. Removals and type changes will not happen inside v1 without notice to you first.