curl --request POST \
--url https://api.paigeme.dev/v1/flows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"instruction": "<string>"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({instruction: '<string>'})
};
fetch('https://api.paigeme.dev/v1/flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.paigeme.dev/v1/flows"
payload = { "instruction": "<string>" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"success": true,
"flow_name": "<string>",
"flow_path": "<string>",
"summary": "<string>",
"screens": 123,
"validation": {},
"meta_flow_id": "<string>",
"meta_status": "<string>",
"meta_validation_errors": [
{}
],
"user_waba_error": "<string>",
"paige_dev": {},
"is_dynamic": true
}
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}Generate a new WhatsApp Flow via the flows sub-agent
Builds a flow from a natural-language instruction — there is no hand-authored flow JSON path. Saves the JSON, records the flow, and drafts it on the connected WABA (never auto-publishes). Consumes credits.
A 200 does not mean the flow was built. The body is one of two shapes: the full result, or a bail-out { "success": false, "error": … } with none of the flow fields (the agent produced no flow, or the run was cancelled). Only a provider-level failure becomes 502. Check success and the presence of flow_name before reading the rest.
Note that success: false on the FULL shape means something narrower — the flow was saved, but Meta raised validation errors or a WABA copy failed. meta_validation_errors / user_waba_error tell you which.
Required scope: flows:write
curl --request POST \
--url https://api.paigeme.dev/v1/flows \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"instruction": "<string>"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({instruction: '<string>'})
};
fetch('https://api.paigeme.dev/v1/flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.paigeme.dev/v1/flows"
payload = { "instruction": "<string>" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"success": true,
"data": {
"success": true,
"flow_name": "<string>",
"flow_path": "<string>",
"summary": "<string>",
"screens": 123,
"validation": {},
"meta_flow_id": "<string>",
"meta_status": "<string>",
"meta_validation_errors": [
{}
],
"user_waba_error": "<string>",
"paige_dev": {},
"is_dynamic": true
}
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}{
"success": false,
"error": {
"code": "invalid_request",
"message": "Invalid request body",
"details": {}
},
"request_id": "<string>"
}Authorizations
Project API key issued in Settings → API keys. Send it as Authorization: Bearer pk_live_….
Headers
Target project id, for an MCP OAuth bearer (mcp_at_…) attached to more than one project — get ids from GET /v1/projects. Matched case-insensitively.
Omit it and a READ falls back to the connection's default project; a mutation (any non-GET) on a connection with 2+ projects is rejected with 400 project_required — a write is never defaulted to a guessed project. A connection with exactly one project never needs the header.
Scopes are checked against the SELECTED project only, never a union across the connection.
For a pk_ API key the header selects nothing — one key is one project's context — but it IS validated: omit it and the key's own project is used, send it and it must name that project, otherwise the call is rejected with 403 project_not_attached (a blank value is 400 invalid_project_header, as above).
Body
Natural-language description of the WhatsApp Flow to build.
1 - 5000Response
Success.
true - Option 1
- Option 2
Hide child attributes
Hide child attributes
True only when Meta raised no validation errors AND both WABA copies were written. Check the error fields below on false — the flow JSON is still saved locally.
Where the JSON was saved, e.g. flows/booking.json.
The agent's description of what it built or changed.
Screen count in the resulting flow.
Paige's own pre-publish validation result.
Flow id on the user's WABA, or null when not connected.
DRAFT | PUBLISHED | LOCAL — LOCAL means saved in Paige only.
Meta's validation errors, empty when it accepted the flow.
Why the user's own WABA copy failed, if it did. Paige Dev is unaffected.
Result of the Paige Dev shared-number publish.
True when the flow declares a data endpoint (dynamic flow).
Was this page helpful?
