Create a submission
POST/v1/flows/:flow_id/submissions
Creates a submission born completed with initiated_by: "api" and runs the same after-effects a WhatsApp completion runs: notifications, the webhook, forwarding to a connected ODK or FHIR server, Sheets, the live Data tab, and the flow's record action when it has one (the response's record_id names the record). The contact goes through the doorway WhatsApp respondents use: matched by phone or created with consent unknown; the API can never assert opt-in. Answer keys are validated against the flow's current published Flow JSON; values are stored as given. Idempotency-Key is required: same key and body replay the stored response as 200 with Idempotent-Replayed: true; a different body or path under the same key is 422; the same key while the first attempt runs is 409. A retry after a timeout or a 5xx is safe with the same key. Every write happens in one transaction, so a 4xx writes nothing: an update-mode flow whose record cannot be resolved from the answer at its record key is 422 record_not_resolved, safe to retry with the same key once the record exists. No Location header is set; the record's id names it. The body is capped at 262144 bytes (256 KB). 404s for a flow that is not this organisation's. Requires the submissions:write scope; a replayed 200 spends the write bucket like any POST.
Request
Responses
- 200
- 201
- 400
- 401
- 403
- 404
- 409
- 413
- 415
- 422
- 429
Replay of an earlier completed request with the same Idempotency-Key and body: the original response, with Idempotent-Replayed: true.
Response Headers
Always true on a replay.
Created: the canonical submission record.
An unrecognised query parameter (code: unknown_parameter), a malformed flow_id, or an Idempotency-Key that is not 1–255 printable ASCII characters (code: invalid_parameter). A missing key is 422 idempotency_key_missing, not a 400.
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="…".
No such flow in this organisation (code: not_found); an existing flow of another organisation answers identically.
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 262144 bytes (256 KB). The detail states the limit and, when the request carried Content-Length, the bytes sent.
code: unsupported_media_type — the body was not application/json.
code: validation_failed (an unknown body key, with a suggestion, or a wrong value), unknown_answer_field (with a suggestion and the known fields), no_published_version, no_number_configured, idempotency_key_missing, idempotency_key_reuse, or record_not_resolved (nothing written).
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.