{"openapi":"3.1.0","info":{"title":"Wabery API","version":"2026-06-18","description":"One API for WhatsApp Business, Instagram Direct, and Facebook Messenger: channels, contacts, conversations, text/media messages, cached inbound files, WhatsApp Flows, templates, automations, signed webhooks, and Meta Business Agent tooling."},"externalDocs":{"description":"Wabery developer documentation","url":"https://wabery.com/docs/"},"servers":[{"url":"https://api.wabery.com/v1"},{"url":"/api/v1"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Use a `wab_live_` API key as a Bearer token."},"publishableKey":{"type":"apiKey","in":"header","name":"x-wabery-publishable-key","description":"A browser-safe `wab_pub_` publishable key. Only valid on the registration-intent endpoints; can mint intents for its own organization and nothing else."}},"parameters":{"WaberyVersion":{"name":"Wabery-Version","in":"header","required":false,"schema":{"type":"string","enum":["2026-06-18"]},"description":"Pin a dated API version. Overrides the organization's pinned version. Defaults to the latest supported version."},"IdempotencyKey":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Retry-safety key. Optional for POST /messages and required for mutating broadcast endpoints; official SDKs generate one automatically."},"BroadcastIdempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":200},"description":"A caller-stable retry-safety key. Reusing it with the same request replays the result; different content returns 409."}},"schemas":{"Error":{"type":"object","additionalProperties":true,"properties":{"error":{"type":"string"},"message":{"type":"string"},"issues":{"type":"object","additionalProperties":true},"required_scope":{"type":"string"}},"required":["error"]},"ListMeta":{"type":"object","properties":{"object":{"type":"string","const":"list"},"has_more":{"type":"boolean"}},"required":["object","data"]},"BusinessAgent":{"type":"object","properties":{"object":{"type":"string","const":"business_agent"},"id":{"type":"string"},"project_id":{"type":"string"},"channel_id":{"type":"string"},"meta_agent_id":{"type":["string","null"]},"status":{"type":"string","enum":["DRAFT","PROVISIONING","ACTIVE","DISABLED","ERROR"]},"settings":{"type":["object","null"],"additionalProperties":true},"eligibility":{"type":["object","null"],"additionalProperties":true},"error_message":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["object","id","project_id","channel_id","status","created_at","updated_at"]},"BusinessAgentApplyRequest":{"type":"object","required":["channel_id"],"additionalProperties":true,"properties":{"channel_id":{"type":"string"},"enabled":{"type":"boolean"},"persona":{"type":"string"},"language":{"type":"string"},"handoff":{"type":"object","additionalProperties":true},"knowledge":{"type":"object","additionalProperties":true}}},"BusinessAgentSettingsRequest":{"type":"object","additionalProperties":true,"properties":{"enabled":{"type":"boolean"},"persona":{"type":"string"},"language":{"type":"string"},"handoff":{"type":"object","additionalProperties":true},"knowledge":{"type":"object","additionalProperties":true}}},"BusinessAgentSettingsResponse":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_settings"},"business_agent_id":{"type":"string"},"settings":{"type":"object","additionalProperties":true}},"required":["object","business_agent_id","settings"]},"BusinessAgentEligibilityResponse":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_eligibility"},"channel_id":{"type":"string"},"eligibility":{"type":"object","additionalProperties":true}},"required":["object","channel_id","eligibility"]},"BusinessAgentConnector":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_connector"},"id":{"type":"string"},"business_agent_id":{"type":"string"},"meta_connector_id":{"type":["string","null"]},"name":{"type":"string"},"type":{"type":"string"},"config":{"type":["object","null"],"additionalProperties":true},"status":{"type":"string"},"tools":{"type":"array","items":{"$ref":"#/components/schemas/BusinessAgentConnectorTool"}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["object","id","business_agent_id","name","type","status","created_at","updated_at"]},"BusinessAgentConnectorCreateRequest":{"type":"object","required":["business_agent_id","name","type"],"additionalProperties":true,"properties":{"business_agent_id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"config":{"type":"object","additionalProperties":true},"status":{"type":"string"}}},"BusinessAgentConnectorUpdateRequest":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"type":{"type":"string"},"config":{"type":"object","additionalProperties":true},"status":{"type":"string"}}},"BusinessAgentConnectorTool":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_connector_tool"},"id":{"type":"string"},"connector_id":{"type":"string"},"meta_tool_id":{"type":["string","null"]},"name":{"type":"string"},"description":{"type":["string","null"]},"backing_type":{"type":"string","enum":["FLOW","API_ENDPOINT","NOOP","HOSTED_FUNCTION"]},"backing_flow_id":{"type":["string","null"]},"backing_function_id":{"type":["string","null"]},"input_schema":{"type":["object","null"],"additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["object","id","connector_id","name","backing_type","created_at","updated_at"]},"BusinessAgentConnectorToolCreateRequest":{"type":"object","required":["name","backing_type"],"additionalProperties":true,"properties":{"name":{"type":"string"},"description":{"type":"string"},"backing_type":{"type":"string","enum":["FLOW","API_ENDPOINT","NOOP","HOSTED_FUNCTION"]},"backing_flow_id":{"type":"string"},"backing_function_id":{"type":"string"},"input_schema":{"type":"object","additionalProperties":true},"config":{"type":"object","additionalProperties":true}}},"BusinessAgentConnectorToolUpdateRequest":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"description":{"type":["string","null"]},"backing_type":{"type":"string","enum":["FLOW","API_ENDPOINT","NOOP","HOSTED_FUNCTION"]},"backing_flow_id":{"type":["string","null"]},"backing_function_id":{"type":["string","null"]},"input_schema":{"type":["object","null"],"additionalProperties":true},"config":{"type":"object","additionalProperties":true}}},"ThreadControlRequest":{"type":"object","required":["action","channel_id","contact_id"],"properties":{"action":{"type":"string","enum":["take","pass","get"]},"channel_id":{"type":"string"},"contact_id":{"type":"string"},"business_agent_id":{"type":"string"},"thread_id":{"type":"string"},"reason":{"type":"string"},"payload":{"type":"object","additionalProperties":true}}},"ThreadControlState":{"type":"object","additionalProperties":true,"properties":{"object":{"type":"string","const":"thread_control_state"},"id":{"type":"string"},"project_id":{"type":"string"},"channel_id":{"type":"string"},"contact_id":{"type":"string"},"business_agent_id":{"type":["string","null"]},"owner":{"type":"string","enum":["META_AGENT","WABERY","BUSINESS_INBOX"]},"reason":{"type":["string","null"]},"meta_thread_id":{"type":["string","null"]},"meta_result":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["object","id","project_id","channel_id","contact_id","owner","created_at","updated_at"]},"BusinessAgentTestRequest":{"type":"object","required":["business_agent_id"],"additionalProperties":true,"properties":{"business_agent_id":{"type":"string"},"input":{"type":"string"},"scenario":{"type":"object","additionalProperties":true}}},"BusinessAgentTestResponse":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_test"},"business_agent_id":{"type":"string"},"result":{"type":"object","additionalProperties":true}},"required":["object","business_agent_id","result"]},"BusinessAgentEvalResponse":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_eval"},"business_agent_id":{"type":"string"},"result":{"type":"object","additionalProperties":true}},"required":["object","business_agent_id","result"]},"BusinessAgentSkillsSetRequest":{"type":"object","required":["business_agent_id","skills"],"additionalProperties":true,"properties":{"business_agent_id":{"type":"string"},"skills":{"type":"array","items":{}}}},"BusinessAgentSkillsResponse":{"type":"object","additionalProperties":true,"properties":{"object":{"type":"string","const":"business_agent_skills"},"business_agent_id":{"type":"string"},"data":{"type":"array","items":{}},"result":{"type":"object","additionalProperties":true}},"required":["object","business_agent_id","data"]},"RegistrationIntent":{"type":"object","properties":{"object":{"type":"string","const":"registration_intent"},"id":{"type":"string"},"token":{"type":"string","description":"Opaque wjr- token."},"status":{"type":"string","enum":["PENDING"]},"mode":{"type":"string","enum":["test","live"],"description":"`live` once the project has its own connected WhatsApp number; `test` (shared sandbox, capped) until then."},"wa_link":{"type":"string","description":"wa.me deep link the customer taps to connect."},"whatsapp_number":{"type":"string"},"prefilled_message":{"type":"string"},"expires_at":{"type":"string","format":"date-time"}},"required":["object","id","token","wa_link","expires_at"]},"Flow":{"type":"object","properties":{"object":{"type":"string","const":"flow"},"id":{"type":"string"},"config_key":{"type":["string","null"],"description":"Stable external key from wabery.config.json, when managed declaratively."},"locale":{"type":["string","null"],"description":"BCP-47 locale of this variant within its config_key group; null is the group default. Send by config_key to resolve the right variant per contact."},"name":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["DRAFT","PUBLISHED","DEPRECATED"]},"meta_status":{"type":["string","null"],"description":"Meta's authoritative approval/health status: DRAFT, PUBLISHED, DEPRECATED, BLOCKED, or THROTTLED. Wabery may also report PUBLISHING or PUBLISH_FAILED while an async publish job is running or failed. A flow is only sendable when PUBLISHED."},"meta_status_reason":{"type":["string","null"],"description":"Human-readable reason for the current meta_status, populated on a failed publish (Meta's error_user_title/error_user_msg). Pair with validation_errors for the actionable detail."},"validation_errors":{"type":["array","null"],"items":{"type":"object","additionalProperties":true},"description":"Meta's validation_errors from the last publish/refresh, with line/field pointers when present. For publish eligibility failures, contains structured details such as Wabery code, Meta code/subcode, fbtrace_id, and next_steps. Empty/null when the flow is valid."},"runtime_mode":{"type":"string","enum":["STATIC","DATA_EXCHANGE"]},"field_schema":{"type":["array","null"],"items":{"type":"object","additionalProperties":true},"description":"Declared submission field schema: [{ name, type, required, screen }]. What flow.completed payloads are validated against."},"flow_json":{"type":["object","null"],"additionalProperties":true,"description":"The compiled Meta WhatsApp Flow JSON (published version if available, else the current draft): screens, routing_model, and data-source bindings. Only present on GET /flows/{id} when requested with `?include=flow_json`. Use it to align a data-exchange endpoint to the compiler's conventions."},"published_version":{"type":["integer","null"],"description":"Version number of the currently published flow_json, or null if the flow has never been published."},"meta_flow_id":{"type":["string","null"]},"meta_waba_id":{"type":["string","null"],"description":"WhatsApp Business Account id that owns `meta_flow_id`. Flow sends require this to match the channel's WABA."},"agent_id":{"type":"string"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Contact":{"type":"object","required":["object","id","contact_id"],"properties":{"object":{"type":"string","const":"contact"},"id":{"type":"string","description":"Canonical contact id. Always present on responses — use this. Equal to `contact_id`; both are stable for a given number within your organization."},"contact_id":{"type":"string","description":"Stable external alias of `id`, kept for backward compatibility. Always present on responses."},"phone":{"type":["string","null"]},"preferred_language":{"type":["string","null"],"description":"BCP-47 language tag used to resolve locale-specific flows when sending by `config_key`."},"project_id":{"type":"string"},"channel_id":{"type":"string"},"channel":{"$ref":"#/components/schemas/Channel"},"reference_id":{"type":["string","null"]},"status":{"type":"string"}}},"PublishReadiness":{"type":"object","properties":{"mode":{"type":"string","enum":["sandbox","dedicated"]},"can_publish_flows":{"type":"boolean"},"can_submit_templates":{"type":"boolean"},"business_verification_status":{"type":["string","null"]},"account_review_status":{"type":["string","null"]},"phone_number_status":{"type":["string","null"]},"blockers":{"type":"array","items":{"type":"string","enum":["CHANNEL_NOT_CONNECTED","MISSING_WABA","MISSING_CHANNEL_CREDENTIALS","META_ACCOUNT_STATUS_UNKNOWN","BUSINESS_NOT_VERIFIED","ACCOUNT_NOT_APPROVED","PHONE_NOT_CONNECTED","PAYMENT_STATUS_UNKNOWN","NO_PAYMENT_METHOD","WHATSAPP_SENDER_NOT_READY","SANDBOX_TEMPLATES_NOT_SUPPORTED"]}}}},"Channel":{"type":"object","properties":{"object":{"type":"string","const":"channel"},"id":{"type":"string"},"channel_id":{"type":"string"},"platform":{"type":"string","enum":["WHATSAPP","INSTAGRAM","MESSENGER","SMS","TELEGRAM","EMAIL"],"description":"Messaging platform. WhatsApp is the default production channel. Instagram Direct and Facebook Messenger are beta channels returned only when activated for the organization; they do not support WhatsApp Flows, WhatsApp templates, or proactive template-style sends."},"status":{"type":"string"},"display_name":{"type":["string","null"]},"phone_number":{"type":["string","null"]},"routing_mode":{"type":"string","enum":["NONE","FLOWS","EXTERNAL"],"description":"How inbound to this channel is handled. EXTERNAL forwards to the project webhook; FLOWS runs native automations; NONE records only. The channel value is authoritative for dedicated numbers and overrides the project's routing_mode."},"number_mode":{"type":"string"},"is_sandbox":{"type":"boolean"},"routing_warning":{"type":["string","null"],"description":"Non-null when this channel's routing is almost certainly a misconfiguration that silently drops inbound (e.g. a FLOWS channel under an EXTERNAL, webhook-backed project). Null when routing looks coherent."},"publish_readiness":{"anyOf":[{"$ref":"#/components/schemas/PublishReadiness"},{"type":"null"}],"description":"WhatsApp Flow/template publishing readiness for this channel. Non-WhatsApp channels return null."}}},"Project":{"type":"object","properties":{"object":{"type":"string","const":"project"},"id":{"type":"string"},"project_id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"routing_mode":{"type":"string"},"join_code":{"type":"string"},"require_opt_in":{"type":"boolean","description":"When true (default), business-initiated sends (targeting `to` or `contact_id`) require an active opt-in/enrollment record; otherwise they return 409 contact_opt_in_required. Set false on a dedicated production number so inbound senders can be replied to and messaged without the invite/enrollment step. Conversation replies (by conversation_id) are always governed by the WhatsApp 24h window, never this flag."},"webhook_url":{"type":["string","null"]},"webhook_signing_enabled":{"type":"boolean","description":"True when a signing secret is set for this project."},"webhook_secret":{"type":["string","null"],"description":"Signing secret for inbound webhooks and outbound data-exchange. Returned only on single GET /projects/{id}, create, update, and rotate — never in the list."},"channel_id":{"type":["string","null"]},"enrollment_channel":{"anyOf":[{"$ref":"#/components/schemas/Channel"},{"type":"null"}]},"publish_readiness":{"anyOf":[{"$ref":"#/components/schemas/PublishReadiness"},{"type":"null"}],"description":"Publishing readiness for the project's effective WhatsApp channel: dedicated channel when connected, otherwise the shared sandbox."},"participant_count":{"type":"number"},"flow_count":{"type":"number"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"FriendlyIssue":{"type":"object","properties":{"code":{"type":"string"},"severity":{"type":"string","enum":["info","warning","blocked"]},"area":{"type":"string"},"title":{"type":"string"},"message":{"type":"string"},"next_steps":{"type":"array","items":{"type":"string"}}}},"ProjectReadiness":{"type":"object","properties":{"object":{"type":"string","const":"project_readiness"},"project_id":{"type":"string"},"project_name":{"type":"string"},"overall_status":{"type":"string","description":"High-level summary such as ready, sandbox_ready, testable_with_blockers, ready_with_warnings, or blocked."},"requirements":{"type":"array","items":{"type":"string"}},"sandbox_testable":{"type":"boolean"},"production_inbound_ready":{"type":"boolean"},"effective_channel":{"anyOf":[{"$ref":"#/components/schemas/Channel"},{"type":"null"}]},"sandbox_channel":{"anyOf":[{"$ref":"#/components/schemas/Channel"},{"type":"null"}]},"dedicated_channel":{"anyOf":[{"$ref":"#/components/schemas/Channel"},{"type":"null"}]},"capabilities":{"type":"object","additionalProperties":{"type":"object","properties":{"status":{"type":"string","enum":["ready","testable","blocked","warning","not_applicable"]},"message":{"type":"string"}}}},"issues":{"type":"array","items":{"$ref":"#/components/schemas/FriendlyIssue"}},"next_steps":{"type":"array","items":{"type":"string"}}}},"ProjectWebhookSecret":{"type":"object","required":["object","project_id","webhook_secret"],"properties":{"object":{"type":"string","const":"project_webhook_secret"},"project_id":{"type":"string"},"webhook_secret":{"type":"string"}}},"Identity":{"type":"object","required":["object","organization","project","api_key"],"properties":{"object":{"type":"string","const":"identity"},"organization":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]}}},"project":{"type":"object","description":"The project this key is scoped to.","properties":{"id":{"type":"string"},"name":{"type":["string","null"]}}},"api_key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"prefix":{"type":["string","null"]},"display":{"type":["string","null"]},"scopes":{"type":"array","items":{"type":"string"}}}},"plan":{"type":["string","null"]},"api_version":{"type":"string"}}},"FlowDispatch":{"type":"object","properties":{"object":{"type":"string","const":"flow_dispatch"},"id":{"type":"string"},"flow_token":{"type":"string"},"flow_id":{"type":"string"},"agent_id":{"type":"string"},"channel_id":{"type":"string"},"conversation_id":{"type":["string","null"]},"contact_id":{"type":["string","null"]},"to":{"type":["string","null"]},"status":{"type":"string","enum":["SENT","COMPLETED","EXPIRED"]},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":"string","format":"date-time"}}},"FlowSubmission":{"type":"object","properties":{"object":{"type":"string","const":"flow_submission"},"id":{"type":"string"},"flow_token":{"type":"string"},"agent_id":{"type":"string"},"flow_id":{"type":"string"},"conversation_id":{"type":["string","null"]},"contact_id":{"type":["string","null"]},"from":{"type":["string","null"]},"status":{"type":"string","enum":["RECEIVED","VALIDATED","REJECTED","FORWARDED"]},"submission":{"type":"object","additionalProperties":true},"created_at":{"type":"string","format":"date-time"}}},"Conversation":{"type":"object","properties":{"object":{"type":"string","const":"conversation"},"id":{"type":"string"},"conversation_id":{"type":"string"},"contact_id":{"type":"string"},"phone":{"type":["string","null"]},"name":{"type":["string","null"]},"reference_id":{"type":["string","null"]},"last_channel_id":{"type":["string","null"]},"is_active":{"type":"boolean"},"started_at":{"type":"string","format":"date-time"},"last_message_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Message":{"type":"object","properties":{"object":{"type":"string","const":"message"},"id":{"type":"string"},"message_id":{"type":"string"},"conversation_id":{"type":["string","null"]},"contact_id":{"type":"string"},"channel_id":{"type":"string"},"direction":{"type":"string","enum":["inbound","outbound"]},"type":{"type":"string"},"status":{"type":"string"},"content":{"type":["string","null"]},"platform_message_id":{"type":["string","null"]},"failure":{"type":["object","null"],"properties":{"provider":{"type":"string","enum":["meta","wabery"]},"summary":{"type":"string"},"code":{"type":["string","number","null"]},"subcode":{"type":["string","number","null"]},"type":{"type":["string","null"]},"title":{"type":["string","null"]},"message":{"type":"string"},"fbtrace_id":{"type":["string","null"]},"http_status":{"type":["integer","null"]},"occurred_at":{"type":"string","format":"date-time"}}},"media":{"type":["object","null"],"description":"Inbound WhatsApp, Instagram, and Messenger media is available through short-lived Wabery signed URLs when cached. Store assets promptly; expires_at is the asset retention deadline.","properties":{"type":{"type":["string","null"]},"file_name":{"type":["string","null"]},"file_size":{"type":["integer","null"]},"mime_type":{"type":["string","null"]},"whatsapp_media_id":{"type":["string","null"]},"provider":{"type":["string","null"],"enum":["whatsapp","instagram","messenger",null]},"provider_media_id":{"type":["string","null"]},"url":{"type":["string","null"]},"accessible":{"type":"boolean"},"expires_at":{"type":["string","null"],"format":"date-time"},"status":{"type":"string","enum":["available","unavailable","expired"]},"access_policy":{"type":"string"},"error_code":{"type":["string","null"]},"note":{"type":["string","null"]}}},"timestamp":{"type":"string","format":"date-time"}}},"PublicApiLimits":{"type":"object","properties":{"object":{"type":"string","const":"public_api_limits"},"rate_limit":{"type":"object","properties":{"requests":{"type":"integer","default":600},"window_seconds":{"type":"integer","default":60},"scope":{"type":"string","const":"api_key"}}},"monthly_quota":{"type":"object","properties":{"requests":{"type":"integer","default":100000},"scope":{"type":"string","const":"api_key"},"period":{"type":"string","example":"2026-06"}}}}},"MessageSendRequest":{"type":"object","required":["channel_id"],"properties":{"channel_id":{"type":"string"},"conversation_id":{"type":"string","description":"Existing conversation id. Provide exactly one of conversation_id or to. Free-form replies require a customer message on the same channel within the last 24 hours. Outside that window, WhatsApp requires an approved template; Instagram/Messenger proactive sends are not exposed."},"to":{"type":"string","description":"Recipient phone in E.164 format. Requires a dedicated channel and an active opt-in record."},"idempotency_key":{"type":"string","maxLength":200,"description":"Optional body-level idempotency key. The Idempotency-Key header is also supported."},"reply_to":{"type":"string","maxLength":200,"description":"WhatsApp message id (wamid) to quote, rendering this message as a reply in a contextual bubble. Works with any content type, and is a modifier rather than a content field — it does not count toward the exactly-one-of rule. Read it from an inbound `messages[].replied_to.message_id` or from a delivery's WhatsApp id."},"text":{"type":"string","minLength":1,"maxLength":4096},"template":{"type":"object","description":"Approved WhatsApp template. Provide either id, or name plus language.","properties":{"id":{"type":"string"},"name":{"type":"string"},"language":{"type":"string"},"components":{"type":"array","description":"Template components. A button component may set `sub_type: \"flow\"` with `index` and a `{ type: \"action\", action: { flow_token, flow_action_data } }` parameter to open a flow from a flow-type template — used for proactive (outside-24h) flow sends.","items":{"type":"object","additionalProperties":true}}}},"media":{"type":"object","description":"Outbound media. WhatsApp accepts `image`, `document`, `video`, and `audio` by public HTTPS `link` or WhatsApp media `id`, with WhatsApp provider limits. Instagram beta accepts `image`, `audio`, and `video` by public HTTPS `link` only. Messenger beta accepts `image`, `document`, `audio`, and `video` by public HTTPS `link` only. Instagram/Messenger links must be directly fetchable by Meta without custom headers; `id`, `caption`, and `filename` return 422 on those channels. Instagram documents return 422 and should be sent as ordinary text links.","x-channel-support":{"WHATSAPP":{"types":["image","document","video","audio"],"locators":["link","id"],"provider_limits":{"image_bytes":5242880,"audio_bytes":16777216,"video_bytes":16777216,"document_bytes":104857600}},"INSTAGRAM":{"types":["image","video","audio"],"locators":["link"],"provider_limits":{"image_bytes":8388608,"audio_bytes":26214400,"video_bytes":26214400},"beta":true},"MESSENGER":{"types":["image","document","video","audio"],"locators":["link"],"provider_limits":{"attachment_bytes":26214400},"beta":true}},"properties":{"type":{"type":"string","enum":["image","document","video","audio"]},"link":{"type":"string","format":"uri"},"id":{"type":"string"},"caption":{"type":"string","maxLength":1024},"filename":{"type":"string","maxLength":240}}},"interactive":{"type":"object","additionalProperties":true,"description":"WhatsApp interactive payload — `type: \"button\"` (1–3 reply buttons), `type: \"list\"` (single-select rows), `type: \"cta_url\"` (one link button, with `display_text` ≤ 20 chars and an http(s) `url`), `type: \"location_request_message\"` (body only; asks the customer to share their location), or `type: \"request_contact_info\"` (body only; asks for the phone number on their WhatsApp account). Shapes are flattened: `buttons` / `sections` / `display_text` sit at the top level, not inside Meta's `action` envelope (a verbatim Meta `action` envelope is also accepted for cta_url). cta_url, location_request_message and request_contact_info are WhatsApp-only and return 422 `interactive_type_unsupported_on_channel` on other platforms. A cta_url tap opens the URL and produces no inbound webhook; a location request comes back as an ordinary inbound location message, not an interactive reply. Provide exactly one of text, template, media, interactive, reaction, location, or sticker."},"reaction":{"type":"object","description":"React to an existing WhatsApp message. Provide exactly one content field.","required":["message_id","emoji"],"properties":{"message_id":{"type":"string","description":"WhatsApp message id to react to."},"emoji":{"type":"string","description":"Emoji reaction. Use an empty string to remove a previous reaction."}}},"location":{"type":"object","description":"Send a WhatsApp location pin. Provide exactly one content field.","required":["latitude","longitude"],"properties":{"latitude":{"type":"number","minimum":-90,"maximum":90},"longitude":{"type":"number","minimum":-180,"maximum":180},"name":{"type":"string","maxLength":1000},"address":{"type":"string","maxLength":1000}}},"contacts":{"type":"array","minItems":1,"maxItems":20,"description":"Contact cards, in Meta's `contacts` shape. Each entry requires `name.formatted_name` plus at least one other name part (first_name, last_name, middle_name, suffix or prefix); a card without one is rejected rather than forwarded. Optional `birthday` (YYYY-MM-DD), `phones` (set `wa_id` to make a number tappable as a WhatsApp contact), `emails`, `urls`, `addresses` and `org`. Provide exactly one content field.","items":{"type":"object","additionalProperties":true}},"sticker":{"type":"object","description":"Send a WhatsApp sticker by public HTTPS link or Meta media id. Provide exactly one of id or link.","properties":{"id":{"type":"string"},"link":{"type":"string","format":"uri"}}}}},"MessageSendResponse":{"type":"object","properties":{"object":{"type":"string","const":"message"},"id":{"type":"string"},"status":{"type":"string","const":"queued"},"conversation_id":{"type":"string"},"contact_id":{"type":"string"},"idempotency_key":{"type":"string"}},"required":["object","id","status","conversation_id","contact_id","idempotency_key"]},"HostedFunction":{"type":"object","properties":{"object":{"type":"string","const":"hosted_function"},"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"trigger_type":{"type":"string","enum":["KEYWORD","WELCOME","ANY_MESSAGE"]},"script_name":{"type":"string"},"runtime":{"type":"string","enum":["PLAIN","WFP"]},"active_version_id":{"type":["string","null"]},"expose_as_mcp_tool":{"type":"boolean"},"input_schema":{"type":["object","null"],"additionalProperties":true,"description":"JSON Schema for external MCP/tool invocation arguments."},"is_active":{"type":"boolean"},"source":{"type":["string","null"],"description":"Current deployed source. Only returned by GET /functions/{id}."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["object","id","slug","name","trigger_type","script_name","runtime","active_version_id","expose_as_mcp_tool","is_active","created_at","updated_at"]},"FunctionCreateRequest":{"type":"object","required":["slug","name","trigger_type"],"properties":{"slug":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[a-z][a-z0-9-]*$"},"name":{"type":"string","minLength":1,"maxLength":120},"trigger_type":{"type":"string","enum":["KEYWORD","WELCOME","ANY_MESSAGE"]}}},"FunctionUpdateRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"expose_as_mcp_tool":{"type":"boolean"},"is_active":{"type":"boolean"},"input_schema":{"type":"object","additionalProperties":true}}},"FunctionDeployRequest":{"type":"object","required":["source"],"properties":{"source":{"type":"string","minLength":1,"maxLength":400000}}},"FunctionDeployResponse":{"type":"object","properties":{"object":{"type":"string","const":"function_deploy"},"function_id":{"type":"string"},"status":{"type":"string","enum":["ok","error"]},"version_id":{"type":"string"},"bytes":{"type":"integer"},"diagnostics":{"type":"array","items":{"type":"string"}}}},"FunctionTestRequest":{"type":"object","properties":{"text":{"type":"string","maxLength":4000},"contact":{"type":"object","required":["id","phone"],"properties":{"id":{"type":"string"},"phone":{"type":"string"},"name":{"type":"string"}}}}},"FunctionTestResponse":{"type":"object","properties":{"object":{"type":"string","const":"function_test"},"function_id":{"type":"string"},"result":{},"error":{"type":"string"}}},"FunctionInvokeRequest":{"type":"object","properties":{"arguments":{"type":"object","additionalProperties":true},"contact_id":{"type":"string"},"contact_phone":{"type":"string"}}},"FunctionInvokeResponse":{"type":"object","properties":{"object":{"type":"string","const":"function_invoke"},"function_id":{"type":"string"},"result":{},"error":{"type":"string"}}},"FunctionInvocation":{"type":"object","properties":{"id":{"type":"string"},"event_type":{"type":"string"},"status":{"type":"string"},"cpu_ms":{"type":["integer","null"]},"sub_requests":{"type":["integer","null"]},"error":{"type":["string","null"]},"logs":{},"started_at":{"type":"string","format":"date-time"}}},"FunctionDeleteResponse":{"type":"object","properties":{"object":{"type":"string","const":"hosted_function"},"id":{"type":"string"},"deleted":{"type":"boolean"}}},"WhatsAppTemplate":{"type":"object","properties":{"object":{"type":"string","const":"whatsapp_template"},"id":{"type":"string"},"channel_id":{"type":"string"},"meta_template_id":{"type":["string","null"]},"name":{"type":"string"},"language":{"type":"string"},"category":{"type":"string"},"status":{"type":"string"},"rejection_reason":{"type":["string","null"]},"components":{"type":"object","additionalProperties":true},"submitted_at":{"type":"string","format":"date-time"},"approved_at":{"type":["string","null"],"format":"date-time"},"rejected_at":{"type":["string","null"],"format":"date-time"},"last_synced_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"TemplateCreateRequest":{"type":"object","required":["channel_id","name","language","category","components"],"properties":{"channel_id":{"type":"string"},"name":{"type":"string","maxLength":512,"pattern":"^[a-z0-9_]+$"},"language":{"type":"string","minLength":2,"maxLength":10},"category":{"type":"string","enum":["UTILITY","MARKETING","AUTHENTICATION"]},"components":{"type":"array","minItems":1,"description":"Template components. A BUTTONS component may include a button of `type: \"FLOW\"` with `flow_id`/`flow_name`, `flow_action`, and `navigate_screen` to embed a flow — required to send flows proactively (outside the 24h window) once Meta approves the template.","items":{"type":"object","additionalProperties":true}}}},"WaberyConfig":{"type":"object","required":["flows","automations"],"properties":{"$schema":{"type":"string"},"version":{"type":"string"},"project_id":{"type":"string"},"require_opt_in":{"type":"boolean","description":"Applied to project_id. False on a dedicated production number lets inbound senders be replied to and messaged without the invite/opt-in step."},"flows":{"type":"array","items":{"type":"object","required":["key","name"],"properties":{"key":{"type":"string"},"locale":{"type":"string","description":"BCP-47 locale of this variant (e.g. \"es\"). Omit (or \"\") for the group default. Multiple entries may share `key` with distinct locales to form a locale group; a send by config_key resolves the variant matching the contact. Two entries sharing `key` with the same locale are rejected."},"name":{"type":"string"},"description":{"type":"string"},"project_id":{"type":"string"},"agent_id":{"type":"string"},"runtime_mode":{"type":"string","enum":["STATIC","DATA_EXCHANGE"]},"data_exchange_url":{"type":["string","null"]},"draft":{"type":"object","description":"Wabery's flow-authoring shape (screens + typed fields + navigation) that compiles to Meta Flow JSON. Provide either `draft` or `flow_json`. See the FlowDraft type in @wabery/sdk.","properties":{"entryScreenId":{"type":"string"},"screens":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true},"flow_json":{"type":"object","description":"Canonical Meta WhatsApp Flow JSON, stored as-is. Provide either `draft` or `flow_json`. See the MetaFlowJson type in @wabery/sdk.","properties":{"version":{"type":"string"},"screens":{"type":"array","items":{"type":"object"}}},"additionalProperties":true}}}},"automations":{"type":"array","items":{"type":"object","required":["key","name","trigger","steps"],"properties":{"key":{"type":"string"},"name":{"type":"string"},"active":{"type":"boolean"},"trigger":{"type":"object","required":["type"],"properties":{"type":{"type":"string","enum":["KEYWORD","WELCOME","ANY_MESSAGE"]},"match_mode":{"type":"string","enum":["EXACT","CONTAINS","CONTAINS_WORD"]},"keywords":{"type":"array","items":{"type":"string"}}}},"steps":{"type":"array","description":"Ordered actions. Each step is exactly one action keyed by its name.","items":{"oneOf":[{"type":"object","required":["send_reply"],"properties":{"send_reply":{"type":"object","required":["text"],"properties":{"text":{"type":"string"},"buttons":{"type":"array","items":{"type":"object","required":["id","title"],"properties":{"id":{"type":"string"},"title":{"type":"string"}}}}}}}},{"type":"object","required":["delay"],"properties":{"delay":{"type":"object","required":["minutes"],"properties":{"minutes":{"type":"integer"}}}}},{"type":"object","required":["wait_reply"],"properties":{"wait_reply":{"type":"object","properties":{"timeout_hours":{"type":"integer"},"options":{"type":"array","items":{"type":"object","required":["id","label"],"properties":{"id":{"type":"string"},"label":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"matchMode":{"type":"string","enum":["EXACT","CONTAINS","CONTAINS_WORD"]}}}}}}}},{"type":"object","required":["pause_replies"],"properties":{"pause_replies":{"type":"object","properties":{"reason":{"type":"string"}}}}},{"type":"object","required":["send_flow"],"properties":{"send_flow":{"type":"object","required":["flow"],"properties":{"flow":{"type":"string"},"body_text":{"type":"string"},"flow_cta":{"type":"string"},"header_text":{"type":"string"},"footer_text":{"type":"string"}}}}},{"type":"object","required":["run_function"],"properties":{"run_function":{"type":"object","required":["function"],"properties":{"function":{"type":"string","description":"Reference to a deployed, active hosted function: its slug or id."},"result_mode":{"type":"string","enum":["reply","variables","side_effect"]},"variable_name":{"type":"string"},"reply_field":{"type":"string"}}}}}]}}}}}}},"ConfigIssue":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"},"severity":{"type":"string","enum":["error","warning"]}}},"ConfigDiffItem":{"type":"object","properties":{"type":{"type":"string","enum":["flow","automation","webhook","project","business_agent","business_agent_connector","business_agent_tool"]},"key":{"type":"string"},"action":{"type":"string","enum":["create","update","delete","unchanged"]}}},"ConfigValidationResponse":{"type":"object","required":["object","valid","issues"],"properties":{"object":{"type":"string","const":"config_validation"},"valid":{"type":"boolean"},"config":{"$ref":"#/components/schemas/WaberyConfig"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/ConfigIssue"}}}},"ConfigDiffResponse":{"type":"object","required":["object","valid","issues","diff"],"properties":{"object":{"type":"string","const":"config_diff"},"valid":{"type":"boolean"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/ConfigIssue"}},"diff":{"type":"array","items":{"$ref":"#/components/schemas/ConfigDiffItem"}}}},"ConfigApplyResponse":{"type":"object","required":["object","valid","issues","diff"],"properties":{"object":{"type":"string","const":"config_apply"},"valid":{"type":"boolean"},"issues":{"type":"array","items":{"$ref":"#/components/schemas/ConfigIssue"}},"diff":{"type":"array","items":{"$ref":"#/components/schemas/ConfigDiffItem"}},"config":{"$ref":"#/components/schemas/WaberyConfig"}}},"ContactDeleteResponse":{"type":"object","required":["object","id","deleted","erased"],"properties":{"object":{"type":"string","const":"contact"},"id":{"type":"string"},"deleted":{"type":"boolean","const":true},"erased":{"type":"boolean"},"deleted_data_types":{"type":"array","items":{"type":"string"}}}},"FlowSendResponse":{"type":"object","required":["object","id","flow_token","flow_id","status"],"properties":{"object":{"type":"string","const":"flow_dispatch"},"id":{"type":"string"},"flow_token":{"type":"string"},"flow_id":{"type":"string"},"locale":{"type":["string","null"],"description":"For sends by config_key, the resolved variant locale (null = group default)."},"conversation_id":{"type":["string","null"]},"contact_id":{"type":["string","null"]},"status":{"type":"string","const":"queued"}}},"FlowPublishResponse":{"type":"object","required":["object","flow_id","job_id","status"],"properties":{"object":{"type":"string","const":"flow_publish"},"flow_id":{"type":"string"},"job_id":{"type":"string"},"status":{"type":"string","const":"queued"},"meta_status":{"type":["string","null"]},"version":{"type":"integer"}}},"FlowDeleteResponse":{"type":"object","required":["object","id","deleted"],"properties":{"object":{"type":"string","const":"flow"},"id":{"type":"string"},"deleted":{"type":"boolean","const":true},"meta_deleted":{"type":"boolean","description":"Whether the Meta-side asset was deleted (draft) or deprecated (published). False if the flow had no Meta asset or the Meta call failed."},"meta_error":{"type":["string","null"],"description":"Meta's error if the Meta-side delete/deprecate failed; the local record is removed regardless."}}},"FlowEvent":{"type":"object","required":["object","id","type","level","created_at"],"properties":{"object":{"type":"string","const":"flow_event"},"id":{"type":"string"},"type":{"type":"string","description":"publish.queued | publish.succeeded | publish.failed | submission.validated | submission.rejected | flow.reconciled"},"level":{"type":"string","enum":["info","warn","error"]},"message":{"type":["string","null"]},"data":{"type":["object","null"],"additionalProperties":true,"description":"Raw structured detail: Meta error_subcode/user_title/validation_errors/fbtrace_id on a publish, or a submission's validation_errors."},"submission_id":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}}},"Broadcast":{"type":"object","required":["object","id","name","status","category","counts"],"properties":{"object":{"type":"string","const":"broadcast"},"id":{"type":"string"},"name":{"type":"string"},"status":{"type":"string","enum":["draft","preparing","ready","scheduled","sending","completed","canceled","failed"]},"category":{"type":"string","enum":["marketing","utility"]},"channel_id":{"type":"string"},"template_name":{"type":"string"},"fallback_language":{"type":"string"},"scheduled_at":{"type":["string","null"],"format":"date-time"},"schedule_timezone":{"type":["string","null"]},"counts":{"type":"object","additionalProperties":{"type":"integer"}},"failure":{"type":["object","null"],"additionalProperties":true},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"BroadcastCreateRequest":{"type":"object","required":["name","channelId","category","templateName","fallbackLanguage","variants"],"properties":{"name":{"type":"string"},"channelId":{"type":"string"},"category":{"type":"string","enum":["MARKETING","UTILITY"]},"templateName":{"type":"string"},"fallbackLanguage":{"type":"string"},"variants":{"type":"array","items":{"type":"object","required":["templateId","language","parameterMappings"],"properties":{"templateId":{"type":"string"},"language":{"type":"string"},"parameterMappings":{"type":"array","items":{"type":"object","additionalProperties":true}}}}}}},"ContactImport":{"type":"object","required":["object","id","status","filename"],"properties":{"object":{"type":"string","const":"contact_import"},"id":{"type":"string"},"status":{"type":"string"},"filename":{"type":"string"},"total_rows":{"type":"integer"},"processed_rows":{"type":"integer"},"created_count":{"type":"integer"},"updated_count":{"type":"integer"},"skipped_count":{"type":"integer"},"error_count":{"type":"integer"},"errors_available":{"type":"boolean"}}}}},"paths":{"/registration-intents":{"post":{"operationId":"registrationIntentsCreate","tags":["Registration intents"],"summary":"Mint a registration intent for the embeddable widget","description":"Creates a single-use token + wa.me deep link so an end-customer can connect over WhatsApp. Authenticate with a `wab_pub_` publishable key (browser; metadata untrusted) or a `wab_live_` secret key with the `registrations:create` scope (server-side; metadata trusted).","security":[{"publishableKey":[]},{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"project_id":{"type":"string","description":"Optional. Keys are project-scoped, so this defaults to the key's project; if provided it must match."},"customer_reference":{"type":"string","description":"Your own id for this end-customer, echoed on participant.joined and message.received."},"metadata":{"type":"object","description":"Arbitrary correlation blob (≤ 8KB), echoed on webhooks for this participant.","additionalProperties":true}}}}}},"responses":{"200":{"description":"The created registration intent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegistrationIntent"}}}},"401":{"description":"Missing or invalid key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/registration-intents/{id}":{"get":{"operationId":"registrationIntentsRetrieve","tags":["Registration intents"],"summary":"Poll a registration intent's status","description":"Returns status fields only. Authenticate with the widget's `wab_pub_` publishable key, or server-side with a `wab_live_` key that has the `registrations:create` scope.","security":[{"publishableKey":[]},{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Status of the intent.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"registration_intent"},"id":{"type":"string"},"status":{"type":"string","enum":["PENDING","JOINED","REJECTED","EXPIRED"]},"rejection_reason":{"type":["string","null"]},"joined_at":{"type":["string","null"],"format":"date-time"},"expires_at":{"type":"string","format":"date-time"}}}}}}}}},"/business-agents":{"get":{"operationId":"businessAgentsList","tags":["Business agents"],"summary":"List Meta Business Agents for the API key's project","parameters":[{"name":"channel_id","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Business Agents.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BusinessAgent"}}}}]}}}}}},"put":{"operationId":"businessAgentsApply","tags":["Business agents"],"summary":"Provision or update a Meta Business Agent","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentApplyRequest"}}}},"responses":{"200":{"description":"Provisioned or updated Business Agent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgent"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Meta Business Agent API failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgent"}}}}}}},"/business-agents/{id}/settings":{"get":{"operationId":"businessAgentSettingsRetrieve","tags":["Business agents"],"summary":"Retrieve live Meta Business Agent settings","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Business Agent settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentSettingsResponse"}}}}}},"put":{"operationId":"businessAgentSettingsUpdate","tags":["Business agents"],"summary":"Update live Meta Business Agent settings","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentSettingsRequest"}}}},"responses":{"200":{"description":"Updated Business Agent settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentSettingsResponse"}}}}}}},"/business-agents/eligibility":{"get":{"operationId":"businessAgentsEligibility","tags":["Business agents"],"summary":"Check Meta Business Agent eligibility for a channel","parameters":[{"name":"channel_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Eligibility response from Meta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentEligibilityResponse"}}}},"400":{"description":"Missing channel id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/business-agents/connectors":{"get":{"operationId":"businessAgentConnectorsList","tags":["Business agents"],"summary":"List Meta Business Agent connectors","parameters":[{"name":"business_agent_id","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Business Agent connectors.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BusinessAgentConnector"}}}}]}}}}}},"post":{"operationId":"businessAgentConnectorsCreate","tags":["Business agents"],"summary":"Create a Meta Business Agent connector","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorCreateRequest"}}}},"responses":{"201":{"description":"Created connector.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnector"}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/business-agents/connectors/{id}":{"get":{"operationId":"businessAgentConnectorsRetrieve","tags":["Business agents"],"summary":"Fetch a Meta Business Agent connector","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Business Agent connector.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnector"}}}}}},"patch":{"operationId":"businessAgentConnectorsUpdate","tags":["Business agents"],"summary":"Update a Meta Business Agent connector","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorUpdateRequest"}}}},"responses":{"200":{"description":"Updated connector.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnector"}}}}}},"delete":{"operationId":"businessAgentConnectorsDelete","tags":["Business agents"],"summary":"Delete a Meta Business Agent connector","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted connector.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_connector"},"id":{"type":"string"},"deleted":{"type":"boolean"},"meta_deleted":{"type":"boolean"}},"required":["object","id","deleted","meta_deleted"]}}}}}}},"/business-agents/connectors/{id}/tools":{"get":{"operationId":"businessAgentConnectorToolsList","tags":["Business agents"],"summary":"List tools for a Meta Business Agent connector","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Connector tools.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BusinessAgentConnectorTool"}}}}]}}}}}},"post":{"operationId":"businessAgentConnectorToolsCreate","tags":["Business agents"],"summary":"Create a tool on a Meta Business Agent connector","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorToolCreateRequest"}}}},"responses":{"201":{"description":"Created connector tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorTool"}}}}}}},"/business-agents/connectors/{id}/tools/{toolId}":{"get":{"operationId":"businessAgentConnectorToolsRetrieve","tags":["Business agents"],"summary":"Fetch a Meta Business Agent connector tool","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"toolId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Connector tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorTool"}}}}}},"patch":{"operationId":"businessAgentConnectorToolsUpdate","tags":["Business agents"],"summary":"Update a Meta Business Agent connector tool","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"toolId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorToolUpdateRequest"}}}},"responses":{"200":{"description":"Updated connector tool.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentConnectorTool"}}}}}},"delete":{"operationId":"businessAgentConnectorToolsDelete","tags":["Business agents"],"summary":"Delete a Meta Business Agent connector tool","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"toolId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted connector tool.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"business_agent_connector_tool"},"id":{"type":"string"},"deleted":{"type":"boolean"},"meta_deleted":{"type":"boolean"}},"required":["object","id","deleted","meta_deleted"]}}}}}}},"/business-agents/thread-control":{"post":{"operationId":"businessAgentsThreadControl","tags":["Business agents"],"summary":"Take, pass, or inspect WhatsApp thread control","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreadControlRequest"}}}},"responses":{"200":{"description":"Thread-control state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreadControlState"}}}}}}},"/business-agents/test":{"post":{"operationId":"businessAgentsTest","tags":["Business agents"],"summary":"Run a Meta Business Agent test scenario","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentTestRequest"}}}},"responses":{"200":{"description":"Business Agent test result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentTestResponse"}}}}}}},"/business-agents/eval":{"get":{"operationId":"businessAgentsEval","tags":["Business agents"],"summary":"Retrieve Meta Business Agent eval summary","parameters":[{"name":"business_agent_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Business Agent eval summary.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentEvalResponse"}}}}}}},"/business-agents/skills":{"get":{"operationId":"businessAgentSkillsList","tags":["Business agents"],"summary":"List Meta Business Agent skills","parameters":[{"name":"business_agent_id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Business Agent skills.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentSkillsResponse"}}}}}},"put":{"operationId":"businessAgentSkillsSet","tags":["Business agents"],"summary":"Set Meta Business Agent skills","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentSkillsSetRequest"}}}},"responses":{"200":{"description":"Updated Business Agent skills.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessAgentSkillsResponse"}}}}}}},"/config":{"get":{"operationId":"configRetrieve","tags":["Config"],"summary":"Export declarative project config including flows, automations, webhooks, and Business Agents","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The current wabery.config.json representation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"wabery_config"},"config":{"$ref":"#/components/schemas/WaberyConfig"}}}}}}}},"put":{"operationId":"configApply","tags":["Config"],"summary":"Validate and apply declarative project config including flows, automations, webhooks, and Business Agents","description":"Creates or updates flows and config-managed automations by stable key. Flow publishing remains explicit via POST /flows/{id}/publish.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaberyConfig"}}}},"responses":{"200":{"description":"Config applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigApplyResponse"}}}},"400":{"description":"Validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigApplyResponse"}}}}}}},"/config/validate":{"post":{"operationId":"configValidate","tags":["Config"],"summary":"Validate declarative config","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaberyConfig"}}}},"responses":{"200":{"description":"Config is valid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigValidationResponse"}}}},"400":{"description":"Config has blocking validation errors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigValidationResponse"}}}}}}},"/config/diff":{"post":{"operationId":"configDiff","tags":["Config"],"summary":"Preview declarative config changes","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WaberyConfig"}}}},"responses":{"200":{"description":"Config diff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigDiffResponse"}}}},"400":{"description":"Config has blocking validation errors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigDiffResponse"}}}}}}},"/config/schema":{"get":{"operationId":"configSchema","tags":["Config"],"summary":"Get the JSON Schema for wabery.config.json","security":[],"responses":{"200":{"description":"JSON Schema document.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}}}}},"/channels":{"get":{"operationId":"channelsList","tags":["Channels"],"summary":"List messaging channels","description":"Returns the project's channel inventory for platforms enabled on the organization, including disconnected channels with their current status. WhatsApp is enabled by default. Instagram Direct and Facebook Messenger are beta channels that appear only after an admin activates them; they are limited to beta inbox/reply use and do not support WhatsApp Flows, WhatsApp templates, or proactive template-style sends. Send requests are accepted only when the selected channel is CONNECTED.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A list of channels, including disconnected project channels for monitoring.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Channel"}}}}]}}}},"401":{"description":"Unauthorized."}}}},"/channels/{id}":{"get":{"operationId":"channelsGet","tags":["Channels"],"summary":"Fetch a channel","description":"Returns a single channel in the key's project, including a routing_warning when its routing silently drops inbound.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The channel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"401":{"description":"Unauthorized."},"404":{"description":"Channel not found, not in the key's project, or its platform is not activated for the organization."}}},"patch":{"operationId":"channelsUpdate","tags":["Channels"],"summary":"Update a channel's routing","description":"Update a dedicated channel's routing_mode (NONE | FLOWS | EXTERNAL) so it can be configured in code/CI instead of dashboard-only. The sandbox channel routes per-participant and cannot be updated this way.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"routing_mode":{"type":"string","enum":["NONE","FLOWS","EXTERNAL"],"description":"EXTERNAL forwards inbound to the project webhook; FLOWS runs native automations; NONE records only."}}}}}},"responses":{"200":{"description":"Channel updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Channel"}}}},"400":{"description":"Invalid request."},"401":{"description":"Unauthorized."},"404":{"description":"Channel not found."},"409":{"description":"The sandbox channel cannot be updated this way."}}}},"/limits":{"get":{"operationId":"limitsRetrieve","tags":["Limits"],"summary":"Get public API rate limits and quotas","description":"Returns the currently enforced per-API-key short-window rate limit and monthly public API request quota. Exceeded limits return 429 with RateLimit-* and Retry-After headers.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The public API limit policy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiLimits"}}}},"429":{"description":"Rate limit or monthly quota exceeded.","headers":{"RateLimit-Limit":{"schema":{"type":"integer"}},"RateLimit-Remaining":{"schema":{"type":"integer"}},"RateLimit-Reset":{"schema":{"type":"integer"}},"Retry-After":{"schema":{"type":"integer"}},"X-Wabery-Limit-Type":{"schema":{"type":"string","enum":["rate_limit","monthly_quota"]}}}}}}},"/me":{"get":{"operationId":"getIdentity","tags":["Identity"],"summary":"Who am I","description":"Identity for the calling API key: organization, key prefix + scopes, and plan. Works with any key.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"Identity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Identity"}}}}}}},"/projects":{"get":{"operationId":"projectsList","tags":["Projects"],"summary":"List projects","description":"Returns the project this key is scoped to (a single-item list). API keys are project-scoped; create new projects from the Wabery dashboard.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A list of projects.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"list"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Project"}}}}}}}}}},"/projects/{id}":{"get":{"operationId":"projectsGet","tags":["Projects"],"summary":"Fetch a project (reveals webhook_secret)","description":"Returns a single project including its webhook_secret, so a deploy can read the signing secret programmatically.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"refresh","in":"query","description":"When true, refreshes the flow status from Meta before returning.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"Project.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"404":{"description":"Project not found."}}},"patch":{"operationId":"projectsUpdate","tags":["Projects"],"summary":"Update a project","description":"Update name, description, or webhook config (url, signing on/off, or a bring-your-own secret). Returns the project with the effective webhook_secret.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"refresh","in":"query","description":"When true, refreshes the template status from Meta before returning.","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":["string","null"],"maxLength":500},"routing_mode":{"type":"string","enum":["NONE","FLOWS","EXTERNAL"],"description":"Default routing for the project. New dedicated channels inherit this, and it determines sandbox routing. Dedicated channels can still be overridden per-channel via PATCH /channels/{id}."},"require_opt_in":{"type":"boolean","description":"When true (default), business-initiated sends require an active opt-in/enrollment record. Set false on a dedicated production number so inbound senders can be replied to and messaged without the invite/enrollment step."},"webhook_url":{"type":["string","null"],"description":"Public HTTPS endpoint, or null to clear it."},"webhook_signing_enabled":{"type":"boolean","description":"true ensures a secret exists; false clears it."},"webhook_secret":{"type":"string","minLength":16,"maxLength":256,"description":"Bring-your-own signing secret."}}}}}},"responses":{"200":{"description":"Project updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Project"}}}},"400":{"description":"Invalid request."},"404":{"description":"Project not found."}}}},"/projects/{id}/readiness":{"get":{"operationId":"projectsGetReadiness","tags":["Projects"],"summary":"Explain project readiness","description":"Returns creator-friendly guidance for what can be tested in the sandbox, what is production-ready, and what blocks WhatsApp templates, proactive sends, routing, or custom submission handling.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"requirements","in":"query","description":"Comma-separated readiness focus areas, e.g. sandbox_test,production_inbound,templates,submission_handling.","schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"Project readiness guidance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectReadiness"}}}},"404":{"description":"Project not found."}}}},"/projects/{id}/rotate-webhook-secret":{"post":{"operationId":"projectsRotateWebhookSecret","tags":["Projects"],"summary":"Rotate the webhook signing secret","description":"Sets a new signing secret (server-generated, or a provided one) and returns it once. The same secret signs inbound webhooks and outbound data-exchange.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"webhook_secret":{"type":"string","minLength":16,"maxLength":256,"description":"Bring-your-own secret; omit to generate one."}}}}}},"responses":{"200":{"description":"New secret (shown once).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProjectWebhookSecret"}}}},"404":{"description":"Project not found."}}}},"/contacts":{"get":{"operationId":"contactsList","tags":["Contacts"],"summary":"List enrolled contacts","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}},{"name":"starting_after","in":"query","schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A paginated list of contacts.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Contact"}}}}]}}}}}},"post":{"operationId":"contactsCreate","tags":["Contacts"],"summary":"Enroll a phone number against a project","description":"Authorizes a phone for the project, records WhatsApp opt-in evidence, and returns the stable `contact_id` plus the WhatsApp `channel_id` to use when sending flows or messages to this contact. A connected dedicated WhatsApp channel is preferred; otherwise enrollment uses the shared sandbox. The same contact_id appears on future flow submissions.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["phone"],"properties":{"phone":{"type":"string","description":"E.164 phone number."},"project_id":{"type":"string","description":"Optional. Keys are project-scoped, so this defaults to the key's project; if provided it must match."},"name":{"type":"string"},"preferred_language":{"type":"string","description":"BCP-47 language tag (e.g. `es`, `id`) used to resolve locale-specific flows when sending by `config_key`."},"reference_id":{"type":"string","description":"Your own id for this person; echoed back as `contact_reference` on submissions."},"metadata":{"type":"object","additionalProperties":true},"opt_in":{"type":"object","description":"Category-specific consent evidence. If omitted, the contact is saved without broadcast eligibility.","properties":{"categories":{"type":"array","items":{"type":"string","enum":["GENERAL","MARKETING","UTILITY","AUTHENTICATION"]}},"source":{"type":"string","description":"Where opt-in was collected, such as checkout, website_form, support_chat, import, or api."},"method":{"type":"string","description":"How opt-in was collected, such as checkbox, keyword, verbal, or form_submit."},"occurred_at":{"type":"string","format":"date-time"},"consent_text":{"type":"string"},"evidence":{"type":"object","additionalProperties":true}}}}}}}},"responses":{"201":{"description":"Contact enrolled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid phone or request."},"404":{"description":"Project not found."}}}},"/contacts/{id}":{"get":{"operationId":"contactsRetrieve","tags":["Contacts"],"summary":"Get an enrolled contact","description":"Returns one enrolled contact by stable contact_id. Use this to verify a phone enrollment before sending a flow.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"404":{"description":"Contact not found."}}},"patch":{"operationId":"contactsUpdate","tags":["Contacts"],"summary":"Update a contact","description":"Update a contact's `preferred_language` and/or `metadata`. `metadata` is shallow-merged with the existing value (set a key to `null` to blank it); `preferred_language` accepts `null` to clear it. Use this to set the locale that resolves locale-specific flows, or to mark enrollment state (e.g. `metadata.linked`) read by gated automations.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preferred_language":{"type":["string","null"],"description":"BCP-47 language tag (e.g. `es`, `id`), or `null` to clear."},"metadata":{"type":"object","additionalProperties":true,"description":"Keys shallow-merged into existing metadata."}}}}}},"responses":{"200":{"description":"The updated contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Contact"}}}},"400":{"description":"Invalid request."},"404":{"description":"Contact not found."}}},"delete":{"operationId":"contactsDelete","tags":["Contacts"],"summary":"Unenroll a contact","description":"By default, removes the phone's authorization on the shared number and retains contact history. Pass `erase=true` to perform org-scoped data erasure for this contact, including opt-in records, messages, conversations, flow submissions, and the contact record when it is no longer referenced.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"erase","in":"query","required":false,"schema":{"type":"boolean"},"description":"When true, performs irreversible org-scoped deletion instead of unenroll-only retention."},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"Contact unenrolled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactDeleteResponse"}}}},"404":{"description":"Contact not found."}}}},"/contact-imports":{"get":{"operationId":"contactImportsList","tags":["Contacts"],"summary":"List contact imports","responses":{"200":{"description":"Contact import jobs."}}},"post":{"operationId":"contactImportsCreate","tags":["Contacts"],"summary":"Import up to 100,000 contacts from CSV","description":"Multipart upload with `file`, JSON `mapping`, optional JSON `defaults`, and optional category-specific JSON `consent` attestation.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","required":["file","mapping"],"properties":{"file":{"type":"string","format":"binary"},"mapping":{"type":"string"},"defaults":{"type":"string"},"consent":{"type":"string"}}}}}},"responses":{"202":{"description":"Import queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImport"}}}}}}},"/contact-imports/{id}":{"get":{"operationId":"contactImportsGet","tags":["Contacts"],"summary":"Get contact import progress","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Import progress and counts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactImport"}}}}}}},"/contact-imports/{id}/errors":{"get":{"operationId":"contactImportsDownloadErrors","tags":["Contacts"],"summary":"Download a CSV of rejected rows","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"CSV error report.","content":{"text/csv":{"schema":{"type":"string"}}}}}}},"/contacts/{id}/consents":{"post":{"operationId":"contactsAddConsent","tags":["Contacts"],"summary":"Record category-specific consent","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Consent recorded."}}}},"/contacts/{id}/suppressions":{"post":{"operationId":"contactsSuppress","tags":["Contacts"],"summary":"Suppress proactive messages to a contact","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Suppression recorded."}}}},"/broadcasts":{"get":{"operationId":"broadcastsList","tags":["Broadcasts"],"summary":"List broadcasts","responses":{"200":{"description":"Paginated broadcasts."}}},"post":{"operationId":"broadcastsCreate","tags":["Broadcasts"],"summary":"Create a draft Meta Cloud broadcast","parameters":[{"$ref":"#/components/parameters/BroadcastIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BroadcastCreateRequest"}}}},"responses":{"201":{"description":"Draft broadcast.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Broadcast"}}}}}}},"/broadcasts/{id}":{"get":{"operationId":"broadcastsGet","tags":["Broadcasts"],"summary":"Get a broadcast","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Broadcast details.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Broadcast"}}}}}},"delete":{"operationId":"broadcastsDelete","tags":["Broadcasts"],"summary":"Delete a draft broadcast","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Draft deleted."}}}},"/broadcasts/{id}/audience":{"post":{"operationId":"broadcastsPrepareAudience","tags":["Broadcasts"],"summary":"Materialize and validate a frozen audience","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/BroadcastIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contactIds":{"type":"array","items":{"type":"string"},"maxItems":1000},"importId":{"type":"string"},"filter":{"type":"object","additionalProperties":true},"excludeContactIds":{"type":"array","items":{"type":"string"},"maxItems":1000}}}}}},"responses":{"202":{"description":"Audience preparation queued."}}}},"/broadcasts/{id}/recipients":{"get":{"operationId":"broadcastsListRecipients","tags":["Broadcasts"],"summary":"List recipients and exclusion reasons","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated recipients."}}}},"/broadcasts/{id}/send":{"post":{"operationId":"broadcastsSend","tags":["Broadcasts"],"summary":"Start a prepared broadcast","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/BroadcastIdempotencyKey"}],"responses":{"202":{"description":"Broadcast dispatch started."}}}},"/broadcasts/{id}/schedule":{"post":{"operationId":"broadcastsSchedule","tags":["Broadcasts"],"summary":"Schedule a prepared broadcast","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/BroadcastIdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["scheduledAt","timezone"],"properties":{"scheduledAt":{"type":"string","format":"date-time"},"timezone":{"type":"string"}}}}}},"responses":{"200":{"description":"Broadcast scheduled."}}}},"/broadcasts/{id}/cancel":{"post":{"operationId":"broadcastsCancel","tags":["Broadcasts"],"summary":"Cancel unsent recipients","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/BroadcastIdempotencyKey"}],"responses":{"200":{"description":"Broadcast canceled."}}}},"/broadcasts/{id}/duplicate":{"post":{"operationId":"broadcastsDuplicate","tags":["Broadcasts"],"summary":"Create an editable copy of a broadcast","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/BroadcastIdempotencyKey"}],"responses":{"201":{"description":"Duplicate draft created."}}}},"/conversations":{"get":{"operationId":"conversationsList","tags":["Conversations"],"summary":"List conversations","description":"Returns organization-scoped conversations so integrators can build their own inbox, support UI, or analytics.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}},{"name":"starting_after","in":"query","schema":{"type":"string"}},{"name":"contact_id","in":"query","schema":{"type":"string"}},{"name":"active","in":"query","schema":{"type":"boolean"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A paginated list of conversations.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"list"},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Conversation"}}}}}}}}}},"/conversations/{id}":{"get":{"operationId":"conversationsRetrieve","tags":["Conversations"],"summary":"Get a conversation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The conversation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Conversation"}}}},"404":{"description":"Conversation not found."}}}},"/conversations/{id}/messages":{"get":{"operationId":"conversationMessagesList","tags":["Messages"],"summary":"List conversation messages","description":"Returns message history for one conversation. Inbound WhatsApp, Instagram, and Messenger media includes fresh short-lived Wabery signed URLs when cached; store assets promptly.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}},{"name":"starting_after","in":"query","schema":{"type":"string"}},{"name":"order","in":"query","schema":{"type":"string","enum":["asc","desc"]}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A paginated list of messages.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"list"},"has_more":{"type":"boolean"},"media_policy":{"type":"object","properties":{"inbound_accessible":{"type":"boolean"},"inbound_access":{"type":"string"},"default_signed_url_ttl_seconds":{"type":"integer"},"free_retention_hours":{"type":"integer"},"paid_retention_days":{"type":"integer"},"note":{"type":"string"}}},"data":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}}}}}},"404":{"description":"Conversation not found."}}}},"/messages":{"post":{"operationId":"messagesSend","tags":["Messages"],"summary":"Send an outbound channel message","description":"Send text or channel-supported media. Instagram and Messenger are beta reply channels and require a customer message on the same channel within the last 24 hours. Unsupported media combinations return 422 before anything is queued.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"},{"$ref":"#/components/parameters/IdempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageSendRequest"},"example":{"channel_id":"channel_...","conversation_id":"conversation_...","text":"Thanks for your message"}}}},"responses":{"202":{"description":"Message queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageSendResponse"}}}},"401":{"description":"Unauthorized."},"409":{"description":"Message was not queued. For ai_handoff_active, the conversation is assigned to a human and public API outbound sends are paused until handoff is turned off. For channel_not_connected, reconnect the channel and retry; Wabery does not hold disconnected-channel sends for later delivery."},"422":{"description":"Message was not queued because the selected channel does not support the requested media type, locator, metadata, or interactive type."}}}},"/messages/{id}":{"get":{"operationId":"messagesGet","tags":["Messages"],"summary":"Retrieve one outbound or inbound message","description":"Returns the latest message status. Use this after POST /messages returns `queued` to check whether Meta accepted, delivered, read, or rejected the send. Failed Meta sends include provider failure details.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"}}}},"403":{"description":"Missing messages:send or conversations:read scope."},"404":{"description":"Message not found."}}}},"/functions":{"get":{"operationId":"functionsList","tags":["Functions"],"summary":"List hosted functions","description":"Returns hosted functions for the authenticated project. Hosted functions are server-side handlers Wabery can run for message triggers, Business Agent tools, or external MCP/tool invocation.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A list of hosted functions.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/HostedFunction"}}}}]}}}},"403":{"description":"Missing functions:read scope."}}},"post":{"operationId":"functionsCreate","tags":["Functions"],"summary":"Create hosted function metadata","description":"Creates function metadata. Deploy source separately with POST /functions/{id}/deploy.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionCreateRequest"}}}},"responses":{"201":{"description":"Hosted function created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostedFunction"}}}},"400":{"description":"Invalid request."},"403":{"description":"Missing functions:write scope."},"409":{"description":"Function slug already exists."}}}},"/functions/{id}":{"get":{"operationId":"functionsGet","tags":["Functions"],"summary":"Get a hosted function","description":"Returns function metadata and the current deployed source when a version exists.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The hosted function.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostedFunction"}}}},"403":{"description":"Missing functions:read scope."},"404":{"description":"Function not found."}}},"patch":{"operationId":"functionsUpdate","tags":["Functions"],"summary":"Update a hosted function","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionUpdateRequest"}}}},"responses":{"200":{"description":"Hosted function updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostedFunction"}}}},"400":{"description":"Invalid request."},"403":{"description":"Missing functions:write scope."},"404":{"description":"Function not found."}}},"delete":{"operationId":"functionsDelete","tags":["Functions"],"summary":"Delete a hosted function","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"Hosted function deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionDeleteResponse"}}}},"403":{"description":"Missing functions:write scope."},"404":{"description":"Function not found."}}}},"/functions/{id}/deploy":{"post":{"operationId":"functionsDeploy","tags":["Functions"],"summary":"Deploy hosted function source","description":"Bundles and deploys a function source file. A successful deploy creates an active immutable version.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionDeployRequest"}}}},"responses":{"200":{"description":"Deploy succeeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionDeployResponse"}}}},"400":{"description":"Invalid request."},"403":{"description":"Missing functions:write scope."},"404":{"description":"Function not found."},"422":{"description":"Bundle or deploy failed."}}}},"/functions/{id}/test":{"post":{"operationId":"functionsTest","tags":["Functions"],"summary":"Test a hosted function","description":"Invokes the function with a synthetic message event and optional contact, returning the function result or error.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionTestRequest"}}}},"responses":{"200":{"description":"Function test completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionTestResponse"}}}},"400":{"description":"Invalid request."},"403":{"description":"Missing functions:write scope."},"404":{"description":"Function not found."},"502":{"description":"Function runtime invocation failed."}}}},"/functions/{id}/logs":{"get":{"operationId":"functionsLogs","tags":["Functions"],"summary":"List hosted function invocation logs","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"Recent invocation logs.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FunctionInvocation"}}}}]}}}},"403":{"description":"Missing functions:read scope."},"404":{"description":"Function not found."}}}},"/functions/{id}/invoke":{"post":{"operationId":"functionsInvoke","tags":["Functions"],"summary":"Invoke an exposed hosted function as a tool","description":"Calls a deployed, active function that has expose_as_mcp_tool enabled. This endpoint uses the functions:invoke scope.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionInvokeRequest"}}}},"responses":{"200":{"description":"Function invocation completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FunctionInvokeResponse"}}}},"400":{"description":"Invalid request."},"403":{"description":"Missing functions:invoke scope or the function is not exposed."},"404":{"description":"Function or contact not found."},"409":{"description":"Function is inactive or has no deployment."},"502":{"description":"Function runtime invocation failed."}}}},"/flows":{"get":{"operationId":"flowsList","tags":["Flows"],"summary":"List flows","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A list of flows.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Flow"}}}}]}}}}}}},"/flows/{id}":{"get":{"operationId":"flowsRetrieve","tags":["Flows"],"summary":"Get a flow","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"refresh","in":"query","required":false,"description":"When `true`, sync the flow's status from Meta before returning.","schema":{"type":"string","enum":["true"]}},{"name":"include","in":"query","required":false,"description":"Comma-separated extras to embed. `flow_json` adds the compiled Meta Flow JSON + `published_version` (omitted by default since it can be large).","schema":{"type":"string","example":"flow_json"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The flow.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Flow"}}}},"404":{"description":"Not found."}}},"delete":{"operationId":"flowsDelete","tags":["Flows"],"summary":"Delete a flow","description":"Removes a flow. A draft Meta asset is hard-deleted; a published one is deprecated (Meta forbids deleting published flows). The local record is removed regardless. Use to clean up failed/test/orphaned flows.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The flow was deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowDeleteResponse"}}}},"404":{"description":"Not found."}}}},"/flows/{id}/events":{"get":{"operationId":"flowsEvents","tags":["Flows"],"summary":"List a flow's lifecycle events","description":"The flow's event log: publish attempts (with Meta's raw reason and validation_errors), submission validation outcomes, and reconciliation. Newest first. Use this to debug a failed publish or a rejected submission without reading worker logs.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"starting_after","in":"query","required":false,"description":"Cursor: an event id to paginate after.","schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A page of flow events.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"list"},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/FlowEvent"}}}}}}},"404":{"description":"Not found."}}}},"/flows/{id}/send":{"post":{"operationId":"flowsSend","tags":["Flows"],"summary":"Send a published flow to an authorized contact","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["channel_id"],"properties":{"channel_id":{"type":"string"},"contact_id":{"type":"string","description":"A contact id from POST /v1/contacts. Provide one of contact_id, conversation_id or to."},"conversation_id":{"type":"string","description":"Existing conversation id. Provide one of contact_id, conversation_id or to. Conversation flow replies require a customer message within the last 24 hours; contact_id/to sends require opt-in."},"to":{"type":"string","description":"Recipient phone (E.164). Provide one of contact_id, conversation_id or to. Requires an active opt-in record."},"flow_cta":{"type":"string","maxLength":20},"body_text":{"type":"string","maxLength":1024},"header_text":{"type":"string","maxLength":60},"footer_text":{"type":"string","maxLength":60},"first_screen":{"type":"string"},"screen_data":{"type":"object","additionalProperties":true}}}}}},"responses":{"202":{"description":"Flow dispatch queued; returns a flow_token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowSendResponse"}}}},"404":{"description":"Flow, channel, conversation or contact not found."},"409":{"description":"Flow not sendable: not yet approved by Meta (flow_not_published), deprecated, blocked, not published for this channel's WABA (flow_not_published_for_channel), or channel not connected. The body includes `meta_status` when applicable."},"422":{"description":"Meta rejected the dispatch request (flow_dispatch_rejected). The body includes upstream provider/status/code/fbtrace_id."},"429":{"description":"Flow is throttled by Meta (flow_throttled)."}}}},"/flows/send":{"post":{"operationId":"flowsSendByConfigKey","tags":["Flows"],"summary":"Send a flow chosen from a locale group by config key","description":"Sends the published flow variant whose `locale` matches the contact's `preferred_language` (or an explicit `locale`), falling back to the group's default (\"\") variant. Flows sharing a `config_key` form the locale group. Use this instead of `/flows/{id}/send` to keep one stable key per logical flow across languages.","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["config_key","channel_id"],"properties":{"config_key":{"type":"string","description":"Stable flow-group key shared by all locale variants."},"locale":{"type":"string","description":"Optional BCP-47 override; defaults to the contact's preferred_language."},"channel_id":{"type":"string"},"contact_id":{"type":"string","description":"A contact id from POST /v1/contacts. Provide one of contact_id, conversation_id or to."},"conversation_id":{"type":"string","description":"Existing conversation id. Provide one of contact_id, conversation_id or to. Conversation flow replies require a customer message within the last 24 hours; contact_id/to sends require opt-in."},"to":{"type":"string","description":"Recipient phone (E.164). Provide one of contact_id, conversation_id or to. Requires an active opt-in record."},"flow_cta":{"type":"string","maxLength":20},"body_text":{"type":"string","maxLength":1024},"header_text":{"type":"string","maxLength":60},"footer_text":{"type":"string","maxLength":60},"first_screen":{"type":"string"},"screen_data":{"type":"object","additionalProperties":true}}}}}},"responses":{"202":{"description":"Flow dispatch queued; returns a flow_token and the resolved `locale`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowSendResponse"}}}},"404":{"description":"No flow for config_key, or channel, conversation or contact not found."},"409":{"description":"No sendable variant: not yet approved by Meta (flow_not_published), deprecated, blocked, not published for this channel's WABA (flow_not_published_for_channel), or channel not connected. The body includes `meta_status` when applicable."},"422":{"description":"Meta rejected the dispatch request (flow_dispatch_rejected). The body includes upstream provider/status/code/fbtrace_id."},"429":{"description":"Flow is throttled by Meta (flow_throttled)."}}}},"/flows/{id}/publish":{"post":{"operationId":"flowsPublish","tags":["Flows"],"summary":"Publish a draft flow to Meta","description":"Queues an async publish job that pushes the current Wabery draft Flow JSON to Meta, publishes it, and snapshots an immutable version. Config apply does not publish flows.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"202":{"description":"Publish accepted and queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowPublishResponse"}}}},"404":{"description":"Flow not found."},"412":{"description":"Project/channel not ready, empty flow, or Meta validation failed. For channel readiness failures, the body includes publish_readiness with blockers such as BUSINESS_NOT_VERIFIED."}}}},"/templates":{"get":{"operationId":"templatesList","tags":["Templates"],"summary":"List WhatsApp message templates","parameters":[{"name":"channel_id","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A list of WhatsApp templates.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WhatsAppTemplate"}}}}]}}}}}},"post":{"operationId":"templatesCreate","tags":["Templates"],"summary":"Create and submit a WhatsApp message template","parameters":[{"$ref":"#/components/parameters/WaberyVersion"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreateRequest"}}}},"responses":{"201":{"description":"Template submitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplate"}}}},"400":{"description":"Invalid request."},"409":{"description":"Channel or template state conflict."},"412":{"description":"Channel cannot submit templates because publish_readiness has blockers such as BUSINESS_NOT_VERIFIED or NO_PAYMENT_METHOD."},"422":{"description":"Channel cannot submit templates."},"502":{"description":"Meta template submission failed."}}}},"/templates/{id}":{"get":{"operationId":"templatesRetrieve","tags":["Templates"],"summary":"Get a WhatsApp message template","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The WhatsApp template.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhatsAppTemplate"}}}},"404":{"description":"Template not found."}}}},"/submissions":{"get":{"operationId":"submissionsList","tags":["Submissions"],"summary":"List completed-flow submissions","parameters":[{"name":"agent_id","in":"query","schema":{"type":"string"}},{"name":"flow_id","in":"query","schema":{"type":"string"}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}},{"name":"starting_after","in":"query","schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A paginated list of submissions.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","const":"list"},"has_more":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/FlowSubmission"}}}}}}}}}},"/dispatches":{"get":{"operationId":"dispatchesList","tags":["Dispatches"],"summary":"List sent flows (the dispatch ledger)","description":"Every flow send creates a dispatch. Track delivery and completion by flow_token. Filter by flow_id, contact_id, and status.","parameters":[{"name":"flow_id","in":"query","schema":{"type":"string"}},{"name":"contact_id","in":"query","schema":{"type":"string"}},{"name":"status","in":"query","schema":{"type":"string","enum":["SENT","COMPLETED","EXPIRED"]}},{"name":"limit","in":"query","schema":{"type":"integer","maximum":100}},{"name":"starting_after","in":"query","schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"A paginated list of dispatches.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/ListMeta"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/FlowDispatch"}}}}]}}}}}}},"/dispatches/{flow_token}":{"get":{"operationId":"dispatchesRetrieve","tags":["Dispatches"],"summary":"Get a single send's status by flow_token","parameters":[{"name":"flow_token","in":"path","required":true,"schema":{"type":"string"}},{"$ref":"#/components/parameters/WaberyVersion"}],"responses":{"200":{"description":"The dispatch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowDispatch"}}}},"404":{"description":"Not found."}}}}},"x-rate-limits":{"scope":"api_key","default_rate_limit":{"requests":600,"window_seconds":60,"environment_overrides":["PUBLIC_API_RATE_LIMIT_REQUESTS","PUBLIC_API_RATE_LIMIT_WINDOW_SECONDS"]},"default_monthly_quota":{"requests":100000,"environment_override":"PUBLIC_API_MONTHLY_QUOTA_REQUESTS"},"enforcement":"All authenticated /api/v1 requests pass through API-key scoped rate and monthly quota checks. Exceeded limits return 429 with RateLimit-* and Retry-After headers."},"x-meta-webhook-security":{"verification":"Meta webhook GET challenges require META_WEBHOOK_VERIFY_TOKEN. POST payloads require X-Hub-Signature-256 verified with FACEBOOK_APP_SECRET. Missing secrets or signatures are rejected.","official_docs":["https://developers.facebook.com/documentation/business-messaging/whatsapp/webhooks/create-webhook-endpoint/","https://developers.facebook.com/docs/graph-api/webhooks/getting-started/"]},"x-webhooks":{"signature":"Wabery sends webhook signatures in the `x-wabery-signature` header as `sha256=<hex>`, where the hex value is HMAC-SHA256 over the exact raw request body using the project's webhook signing secret.","flow.completed":{"post":{"summary":"Sent when a contact completes a flow","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"flow.completed"},"api_version":{"type":"string"},"payload":{"type":"object","properties":{"object":{"type":"string","const":"flow_submission"},"api_version":{"type":"string"},"id":{"type":"string"},"flow_token":{"type":"string"},"organization_id":{"type":"string"},"agent_id":{"type":"string"},"flow_id":{"type":"string"},"flow_version":{"type":["integer","null"]},"conversation_id":{"type":["string","null"]},"contact_id":{"type":["string","null"]},"contact_reference":{"type":["string","null"],"description":"The reference_id supplied when the contact was enrolled."},"from":{"type":["string","null"]},"valid":{"type":"boolean"},"submission":{"type":"object","additionalProperties":true},"submitted_at":{"type":"string","format":"date-time"}}},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Acknowledged."}}}},"message.received":{"post":{"summary":"Sent when Wabery receives an inbound customer message","description":"Delivered to the project's webhook URL for inbound WhatsApp Business, Instagram Direct, and Facebook Messenger messages.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"message.received"},"api_version":{"type":"string"},"payload":{"type":"object","properties":{"agent_id":{"type":"string"},"organization_id":{"type":"string"},"channel_id":{"type":"string"},"conversation_id":{"type":["string","null"]},"contact_id":{"type":["string","null"]},"from":{"type":["string","null"],"description":"Sender's E.164 phone number on WhatsApp; null on Instagram/Messenger."},"user_id":{"type":["string","null"],"description":"Instagram-scoped or Page-scoped sender ID on Instagram/Messenger; null when unavailable."},"text":{"type":["string","null"]},"message_id":{"type":"string"},"type":{"type":["string","null"],"enum":["text","image","audio","video","document","location","sticker","reaction","interactive","template",null],"description":"Type of the latest message in this delivery."},"ai_handoff":{"type":"object","description":"Current handoff state for this conversation. When handoff is on, Wabery pauses native automations, external webhook forwarding, and public API outbound sends for this conversation.","properties":{"status":{"type":"string","enum":["AI_ACTIVE","PENDING_HUMAN","HUMAN_ASSIGNED"]},"reason":{"type":["string","null"]},"handoff_at":{"type":["string","null"],"format":"date-time"},"is_on_hold":{"type":"boolean"}}},"messages":{"type":"array","description":"Ordered inbound messages in this delivery. Media URLs are short-lived Wabery signed URLs; expires_at is the asset retention deadline (24h on free plans, 7d on paid plans). Check media.status before downloading.","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string"},"text":{"type":["string","null"]},"received_at":{"type":"string","format":"date-time"},"media":{"type":["object","null"],"properties":{"id":{"type":"string"},"message_id":{"type":"string"},"type":{"type":"string"},"url":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"mime_type":{"type":["string","null"]},"file_name":{"type":["string","null"]},"file_size":{"type":["number","null"]},"provider":{"type":"string","enum":["whatsapp","instagram","messenger"]},"provider_media_id":{"type":["string","null"]},"status":{"type":"string","enum":["available","unavailable","expired"]},"error_code":{"type":["string","null"]}}},"location":{"type":["object","null"],"properties":{"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"name":{"type":["string","null"]},"address":{"type":["string","null"]}}},"interactive":{"type":["object","null"],"description":"Tap metadata when type is 'interactive'. 'id' is the id you set on the reply button or list row when sending — route on it. 'title' is the visible label and changes with translation. For 'nfm_reply' (WhatsApp Flow), 'id' holds the raw response_json.","properties":{"type":{"type":"string","enum":["button_reply","list_reply","nfm_reply","button"]},"id":{"type":["string","null"]},"title":{"type":["string","null"]}}},"replied_to":{"type":["object","null"],"description":"Set when the customer replied to a specific message. 'message_id' is the quoted message's WhatsApp id (wamid) — the same value you pass as 'reply_to' when sending. Null for a fresh message.","properties":{"message_id":{"type":"string"},"from":{"type":["string","null"]}}}}}},"assets":{"type":"array","description":"Flattened media assets from messages. Download and store promptly; the URL is short-lived, expires_at is the asset retention deadline, and status reports cache availability."},"media":{"type":["object","null"],"description":"Latest media asset in the delivery."},"location":{"type":["object","null"],"description":"Latest location in the delivery."},"interactive":{"type":["object","null"],"description":"Latest interactive tap in the delivery. Same shape as messages[].interactive."},"contact_reference":{"type":["string","null"],"description":"Your own id for this contact (reference_id / externalId). Canonical name across all events."},"customer_reference":{"type":["string","null"],"description":"Alias of contact_reference (same value), kept for backward compatibility."},"metadata":{"type":["object","null"],"additionalProperties":true}}},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Acknowledged."}}}},"message.status":{"post":{"summary":"Sent when an outbound message status changes","description":"Notifies the integrator when a sent message becomes sent, delivered, read, or failed. Failed events include Meta failure details when available.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"message.status"},"api_version":{"type":"string"},"payload":{"type":"object","properties":{"object":{"type":"string","const":"message_status"},"message_id":{"type":"string"},"platform_message_id":{"type":["string","null"]},"conversation_id":{"type":["string","null"]},"contact_id":{"type":"string"},"channel_id":{"type":"string"},"status":{"type":"string","enum":["sent","delivered","read","failed"]},"occurred_at":{"type":"string","format":"date-time"},"recipient_id":{"type":["string","null"]},"conversation":{"type":["object","null"],"additionalProperties":true},"pricing":{"type":["object","null"],"additionalProperties":true},"failure":{"type":["object","null"],"properties":{"provider":{"type":["string","null"],"enum":["meta","wabery",null]},"summary":{"type":["string","null"]},"code":{"type":["string","number","null"]},"subcode":{"type":["string","number","null"]},"type":{"type":["string","null"]},"title":{"type":["string","null"]},"message":{"type":["string","null"]},"fbtrace_id":{"type":["string","null"]},"http_status":{"type":["integer","null"]},"raw_errors":{"type":"array","items":{}}}}}},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Acknowledged."}}}},"flow.status":{"post":{"summary":"Sent when Meta reports a flow status change","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"flow.status"},"api_version":{"type":"string"},"payload":{"type":"object","properties":{"object":{"type":"string","const":"flow_status"},"flow_id":{"type":"string"},"meta_flow_id":{"type":"string"},"status":{"type":"string"},"meta_status":{"type":"string"},"meta_status_reason":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}}},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Acknowledged."}}}},"template.status":{"post":{"summary":"Sent when Meta reports a WhatsApp template status change","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"template.status"},"api_version":{"type":"string"},"payload":{"type":"object","properties":{"object":{"type":"string","const":"whatsapp_template_status"},"template_id":{"type":"string"},"channel_id":{"type":"string"},"meta_template_id":{"type":["string","null"]},"name":{"type":"string"},"language":{"type":"string"},"category":{"type":"string"},"status":{"type":"string"},"rejection_reason":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"}}},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Acknowledged."}}}},"participant.joined":{"post":{"summary":"Sent when a sandbox participant joins a project","description":"Sent for shared sandbox-number registration flows when an end user authorizes a project.","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"participant.joined"},"api_version":{"type":"string"},"payload":{"type":"object","properties":{"object":{"type":"string","const":"participant"},"agent_id":{"type":"string"},"organization_id":{"type":"string"},"channel_id":{"type":"string"},"contact_id":{"type":"string"},"from":{"type":"string","description":"Joiner's E.164 phone number."},"customer_reference":{"type":["string","null"]},"metadata":{"type":["object","null"],"additionalProperties":true},"intent_id":{"type":"string"},"joined_at":{"type":"string","format":"date-time"}}},"sentAt":{"type":"string","format":"date-time"}}}}}},"responses":{"200":{"description":"Acknowledged."}}}}}}