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 acode 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.
