Create a flow
POST/v1/flows
Creates the flow and its first version, from Flow JSON (application/json) or from an uploaded XLSForm or FHIR Questionnaire (multipart/form-data, a source_form file part beside the metadata fields). Never both. A source form is converted before this responds; its problems are immediate: 422 conversion_failed with the converter's sentence, 504 converter_timeout, 502 converter_unavailable. The response is 202: the flow exists and its first version is pending while WhatsApp processes it. Poll GET /v1/flows/{flow_id}/versions/{version_id} with latest_version.id until state leaves pending; a rejected document is failed with failure_reason, an accepted one draft with a preview_url, and publishable says when it can be published. warnings lists what the converter dropped or degraded; it is empty for Flow JSON. number_id defaults to your organisation's number (422 no_number_configured when it has none) and must be one of yours. record_action is not accepted here; set it through PUT /v1/flows/{flow_id}/record-action once the version has left pending, then publish. Bodies up to 5 MB. Idempotency-Key is accepted but not required: send one and a retry of the same request replays the first response as 200 with Idempotent-Replayed: true instead of creating a second flow. Requires the flows:write scope.
Request
Responses
- 200
- 202
- 400
- 401
- 403
- 409
- 413
- 415
- 422
- 429
- 502
- 504
Replay of an earlier completed request with the same Idempotency-Key and body: the original response, with Idempotent-Replayed: true. Nothing was created a second time.
Response Headers
Always true on a replay.
The flow, with its first version pending and the converter's warnings.
An Idempotency-Key that is not 1–255 printable ASCII characters (code: invalid_parameter).
Missing, malformed, unknown, revoked, or expired key — one body for all of them (code: unauthorized), with WWW-Authenticate: Bearer realm="hop".
The key lacks the scope (code: insufficient_scope), named in WWW-Authenticate: Bearer error="insufficient_scope", scope="…".
code: in_flight — an earlier request with this Idempotency-Key is still being processed, or took the key over after this attempt stalled. Retry shortly with the same key.
code: request_too_large — the body exceeded 5242880 bytes (5 MB). The detail states the limit and, when the request carried Content-Length, the bytes sent.
code: unsupported_media_type — the body was neither application/json nor multipart/form-data.
code: validation_failed (an unknown or invalid field, a repeated name, a number that is not yours), conversion_failed, no_number_configured, or idempotency_key_reuse.
Over a bucket. Obey Retry-After (seconds); RateLimit-* fields are informational.
Response Headers
Requests allowed in the current window. Informational.
Requests left in the current window. Informational.
Seconds until the window resets. Informational.
Seconds to wait before retrying. The binding contract.
code: converter_unavailable or storage_unavailable — nothing was created; retry.
code: converter_timeout — the source form did not convert inside the budget; nothing was created.