x-api-key) whose number is a Meta (Cloud API) number. The WABA is derived from that number — there is no parameter to name one, by design.
flows:read is a slug of its own and is not templates:read. A template listing returns text your workspace wrote; a Flow response returns what a customer typed into a form — a name, a phone, sometimes a document number. The two are gated separately on purpose.List Flows
id is the local id and is the only id you ever send back to us. metaFlowId is Meta’s own and is read-only — it is null while a Flow exists here but has not reached Meta.Create or clone
201 with the new Flow in DRAFT. Omit cloneFromFlowId to start from scratch.
Rename and re-categorize
name and categories. This never publishes and never deprecates — those have endpoints of their own, so that a mistake in a form cannot reach an irreversible operation.
Upload the Flow JSON
200 means the document compiled, and validationErrors is then always empty:
422 FLOW_JSON_INVALID, with Meta’s own list attached:
Publish
Deprecate
supersededByFlowId is optional — but if you send it, it must name a real Flow of yours: an empty string is refused rather than silently ignored, because a broken version chain is invisible afterwards.
Delete
DRAFT can be deleted. Anything else returns 409.
Read form responses
data_exchange endpoint key
Not yet exposed on the public API. The key management for the
data_exchange endpoint — generating the keypair, registering the public half with Meta, and reading back whether Meta still holds ours — is built, but has no REST endpoint yet. This section will list it here the day it does.What the feature does, and the design behind it, is described in Flows. If you need it before it is exposed, talk to support.Errors
Every failure of this surface answers the same envelope — there is exactly one shape to read, and one spelling:FLOW_JSON_INVALID adds a validationErrors array; FLOW_UNKNOWN_FIELDS adds the offending keys. Never assume the set of codes is closed — branch on the ones you handle and fall through to code for the rest.
The last two carry no
FLOW_ prefix — they are shared across the public API and keep their global spelling. A client matching on code.startsWith("FLOW_") would miss both.