{
    "openapi": "3.1.0",
    "info": {
        "title": "Momo Business Customer API",
        "version": "3.8.0",
        "description": "Customer integration reference for REST messaging, contacts, leads, catalogues, orders, payments, automations, data tables, agent tasks and MCP transport. Use the developer handbook at `/api-docs` for complete workflows and operational guidance.\n\n## Authentication\n\nCreate an account REST key at `/app/api-credentials` and send `Authorization: Bearer <key>`. `/api/v3` and `/api/engine` use REST keys; MCP requires its own connection credential or OAuth token. Keys are scoped to an account. Data, group, payment and automation endpoints additionally enforce the issuer permissions described on each operation.\n\n## Response families\n\nMost v3 successes are `{status: \"success\", data: ...}` and errors are `{status: \"error\", message, errors?}`. Data endpoints intentionally return native `{tables}`, `{records,...}` or `{record}` objects, and expected data-domain failures carry `{error: {code, message, retryable, ...}, message, code, errors?}`. Payment lists return `{data: [...], meta: {...}}`; automation reads return `{events,...}`, `{subscriptions}` or `{schedules}`. Agent endpoints return execution-specific objects; MCP uses JSON-RPC. Consult each response schema rather than assuming a universal envelope.\n\n## Limits and delivery\n\nThe v3 route limit is 120 requests/minute per Bearer token. Throttled requests provide Retry-After; authentication failures can occur before rate headers are attached. Provider throughput limits are separate. Agent and MCP routes have their own contracts.\n\nSMS and WhatsApp sends normally attempt provider delivery inside the request. HTTP 201 means message records were created, including records whose status is failed. Future schedules, admission deferral or fallback can return queued. Save every message UID and inspect its status. Ordinary message and campaign POSTs do not implement request-key idempotency; agent task submission does.\n\n## Identifiers\n\nMessage, campaign and contact lookups accept their public UID or numeric ID. Catalogue, product, order and WhatsApp group resource paths use numeric local IDs. Data tables, groups and records use UUIDs. Provider message IDs, provider catalogue IDs and retailer IDs are distinct from local identifiers."
    },
    "servers": [
        {
            "url": "https://business.momo.tz",
            "description": "Production"
        }
    ],
    "security": [
        {
            "BearerToken": []
        }
    ],
    "tags": [
        {
            "name": "Authentication",
            "description": "Send `Authorization: Bearer <REST key>`. Create and revoke keys at `/app/api-credentials`; the plaintext is returned once. Tenant identity comes from the key, never a request tenant_id.\n\nData and WhatsApp group endpoints check the key issuer's current permissions; a missing/deactivated issuer is refused there. Legacy message, campaign, contact, catalogue and profile controllers use the tenant credential without this per-action permission map. Treat REST keys as powerful credentials.\n\nMissing, invalid, revoked, expired or wrong-kind REST credentials return 401. A suspended/inactive account returns 403. REST API keys and MCP credentials cannot be interchanged."
        },
        {
            "name": "SMS",
            "description": "Send single or bulk SMS, create SMS campaigns against contact groups, and read back message and campaign state. `GET /api/v3/sms/senders` lists the identities a message can be sent as."
        },
        {
            "name": "WhatsApp",
            "description": "Send WhatsApp text, media, template, interactive and reaction messages, and read back message state. Free-text sends are only delivered inside the 24-hour customer service window; outside it, use an approved template. `GET /api/v3/whatsapp/accounts` lists the business accounts and the numbers a message can be sent from."
        },
        {
            "name": "WhatsApp groups",
            "description": "Groups of up to 8 people created from a business number. Invite-only: you send the link, they choose to join. Needs an Official Business Account. Group events also arrive as webhooks (group.created, group.participant_joined, \u2026).\n\nA key here inherits the permissions of the user who created it: `communications.groups.view` to read, `communications.groups.manage` to change a group, and both that and `communications.send` to post into one. A key with no creator on record is refused."
        },
        {
            "name": "WhatsApp templates",
            "description": "Message templates on a WhatsApp Business Account: the pre-approved copy WhatsApp requires before a business may start a conversation. Create one here (in Meta's own `components` shape or with flat fields), it is submitted to Meta for review in the same request, and the answer comes back three ways \u2014 `GET` the template, `POST \u2026/refresh` to ask Meta right now, or subscribe to the `template.status_changed` webhook. `POST \u2026/sync` imports every approved template the account already has. Reads need the issuer's `communications.templates.view` permission, writes `communications.templates.manage`. A template is one name in one language on one business account; another language is another template, and another account is a deployment (`POST \u2026/deployments`)."
        },
        {
            "name": "WhatsApp forms",
            "description": "Forms customers fill in inside WhatsApp (Meta calls them WhatsApp Flows): build one from a definition, publish it to WhatsApp, send it to a phone number or a conversation, and read the answers. Answers also arrive by webhook as `form.submitted`. Every endpoint needs the issuing user's `forms.*` permission and the Forms module switched on."
        },
        {
            "name": "Shop links and baskets",
            "description": "Links to your shop page \u2014 the menu, a category or a product \u2014 that answer back to a WhatsApp chat: the basket the customer sends comes back to that chat as an order. And the baskets themselves, in one shape whatever door they came through (the shop page, a chat link, an AI agent, this API). Baskets also arrive by webhook as `cart.submitted` and `cart.abandoned`."
        },
        {
            "name": "Contacts",
            "description": "The account's contact directory: groups, the people in them, and the custom fields a group declares. `GET /api/v3/contact-groups` is where the `{group_id}` every contact path takes comes from. Contacts are reachable two ways \u2014 the five original `/contacts/{group_id}/\u2026` paths, and ordinary REST under `/contact-groups/{group}/contacts` \u2014 and both do the same thing to the same records. A group or a contact may be named by its numeric id or by its UID. Reading needs the issuer's `contacts.view`; writing needs `contacts.create` / `contacts.edit`; deleting needs `contacts.delete`; the bulk import needs `contacts.import`. A key created before 7 September 2026 has no recorded issuer; those keep the five original `/contacts/{group_id}/\u2026` paths they were issued under and are refused on everything added since. Rotate one from Settings \u2192 API credentials to bring it under the permission model."
        },
        {
            "name": "Leads",
            "description": "Every potential customer, at any stage, in one pipeline. A lead is one person's sales record \u2014 new, contacted, qualified, opportunity, won, lost or unqualified \u2014 attached to the calls, chats, comments and form answers it came through. The AI agent writes leads during chats and after calls, staff work them in the dashboard, and this API is the same door for your CRM.\n\n**One lead per person.** `POST /api/v3/leads` is an upsert: the person is found through the workspace's identity layer \u2014 a phone number (in any common form), a WhatsApp id or an email all resolve to the same person \u2014 and their lead is updated, or created if they have none. Send a `conversation_id` or `call_id` to attach that record and identify the customer by it.\n\n**Who sees what.** A key inherits its issuer's permissions (`leads.view` to read, `leads.edit` to write, `leads.assign`, `leads.delete`, `leads.settings` for the rest) and visibility: without `leads.data.all` a key sees the issuer's leads, the unassigned pool and the ones the issuer added. The module can be switched off per workspace; its endpoints then answer 403.\n\n**Refusals carry a code.** Besides `message`, a refused write returns `reason` \u2014 `invalid`, `reason_required`, `nothing_to_identify`, `won_locked`, `assignee_unknown` \u2014 so a sync can branch on it.\n\n**Events.** Subscribe a webhook to `lead.created`, `lead.updated`, `lead.stage_changed`, `lead.label_added`, `lead.label_removed`, `lead.note_added`, `lead.assigned`, `lead.merged` and `lead.deleted` to keep another system in step; see the Webhooks tag."
        },
        {
            "name": "Catalogue",
            "description": "Read existing shops, manage products, send WhatsApp product messages and inspect customer orders. Resource paths use local numeric IDs; commerce sends use provider catalogue IDs and product retailer IDs. Product price/sale_price and order total_amount use integer hundredths; these differ from data-table currency fields.\n\nProduct send endpoints call the provider directly and return its message_id, not a local Message UID. Product synchronization is not an atomic transaction across the local store and provider. Order status updates accept the documented enum and record history without enforcing a linear transition graph or performing a payment refund."
        },
        {
            "name": "Data tables",
            "description": "Read schemas and operate on account-defined business records. Tables, groups and records use UUIDs. Read permissions are data.view; record writes need data.records.edit plus table access. Schema responses describe types, masks, grants, unique sets, quotas and state rules.\n\nRecord pages use next_cursor/has_more, with a default limit of 50 and maximum 200. Record PATCH merges submitted keys, with null clearing an optional value. Source stays fixed at creation. State changes are enforced; history is an audit trail, not a record-version rollback API.\n\nData responses have native envelopes. Expected refusals contain a structured error object: validation_error 422, conflict 409, quota_exceeded 402, not_found 404, permission_denied 403, not_supported 501, rate_limited 429, provider_failure 502 or temporary_failure 503. Framework/authentication failures can use the standard v3 error envelope."
        },
        {
            "name": "Payments",
            "description": "Money this business collects from ITS customers, and money it sends out. Not the same thing as the business's own Momo bill, which lives under Profile & Balance. Reads only: asking a customer for money or refunding one goes through a surface attributable to a person, never a long-lived API key."
        },
        {
            "name": "Profile & Balance",
            "description": "The tenant behind the token and its wallet balance."
        },
        {
            "name": "Webhooks",
            "description": "Two customer callback protocols are documented here. Communication callbacks \u2014 messages, orders, groups, forms, leads \u2014 use X-Signature / X-Signature-V2 and a flat event payload carrying a stable `event_id`, retried five times (1 m, 5 m, 30 m, 2 h, 6 h) before a delivery is marked failed. Automation subscription callbacks use X-Momo-Signature over a signed timestamp and raw body, a business-event envelope and bounded retries. These are requests sent to your receiver, not callable paths on this API. Read the corresponding webhook entry before implementing signature verification."
        },
        {
            "name": "Automations",
            "description": "What this business has arranged to happen without a person: the log of business events, the subscriptions that react to them, and the schedules that run on a rhythm. Reads only \u2014 creating an automation is a decision made on a screen or through an MCP connection with an explicit elevation, never with a long-lived key."
        },
        {
            "name": "Operations",
            "description": "The named things this business can do \u2014 create a booking, register a customer, process a refund \u2014 each written down once by the business and callable from a chat flow, a phone menu, an assistant or your own code. An operation validates its inputs before anything happens, runs its steps inside a compensating transaction, and records every run with its inputs, its outputs and per-step timing.\n\nThis is the one write these platform phases added to v3, and deliberately: an operation can only do what somebody in the workspace already defined for it, so a key calling `create_booking` cannot make it do anything but create a booking. The definitions themselves are written on the Operations page or through an MCP connection \u2014 never with a long-lived key."
        },
        {
            "name": "Agent tasks",
            "description": "Submit prompts to configured account agents and poll run progress. Uses a REST API key at /api/engine, with native run envelopes and optional Idempotency-Key protection.\n\nThe account engine, agent profile and API availability must permit execution. Tasks may incur usage. Queued acceptance is 202; sync HTTP 200 still requires checking the run status. This route group is separate from the v3 shared throttle and error renderer."
        },
        {
            "name": "Flows",
            "description": "Message flows \u2014 the WhatsApp conversations a workspace scripts in the builder \u2014 and their sessions. Read flows, publish a draft, export a bundle, list and end sessions, start one for a customer. The graph itself is edited in the builder or over MCP, never here. Subscribe a webhook to flow.session.started / flow.session.ended for the CRM side."
        },
        {
            "name": "Posts",
            "description": "Social publishing: drafts, scheduling and publishing to Facebook Pages, Instagram, TikTok, YouTube and LinkedIn \u2014 the same posts the composer makes, over an API key. Reads need posts.view, writes posts.manage, on the person who issued the key; what that person is assigned to bounds what the key sees."
        },
        {
            "name": "Occasions",
            "description": "Occasion greetings: a year of Tanzanian, religious and world occasions a workspace can greet its customers on by SMS \u2014 Christmas, Eid, Saba Saba, Black Friday and twenty-three more. Each is a **card**: the catalogue's facts (when it falls, the standard wording in English and Kiswahili) plus the workspace's decisions (on/off, own wording, sender ID, audience, time of day, a corrected date for the lunar holidays). A card stores only what it overrides and `inherited` names the fields that fell through to the workspace defaults or the catalogue, so an integration keeps nothing but the choices it made. Switching one on schedules a real bulk SMS on the day, through the same campaign machinery as `POST /api/v3/sms/campaign`; `POST /api/v3/occasions/{key}/send` sends it now. Reads need `communications.campaigns.view` on the key's issuer, writes `communications.campaigns.manage`."
        },
        {
            "name": "Voice",
            "description": "Voice codes and voice messages: ring a phone and say something. `POST /api/v3/voice/otp` says a one-time code by joining pre-recorded clips from a **voice pack** (digits 0-9, a falling last digit, \"Msimbo wako ni\", \"Narudia\"), so there is no text-to-speech per call and nothing to pay beyond the call minute; the person presses 1 to hear it again. `POST /api/v3/voice/messages` speaks your sentence in a chosen voice: the audio is generated the first time those words are used in that voice (charged per character, at the voice model's rate) and reused free after that. Both answer 202 \u2014 the call is queued \u2014 and report the rest through `voice.otp.*` / `voice.message.*` webhooks and the status endpoints. Only listed countries are rung (Tanzania, +255, by default), and each number gets at most 3 codes in 10 minutes. Sending needs `calls.place` on the key's issuer; reading needs `calls.view`."
        },
        {
            "name": "Calls",
            "description": "One call placed now, and the workspace's calls read back. `POST /api/v3/calls` rings a number with a message and keys, an AI agent or an IVR flow \u2014 the same call a campaign person gets \u2014 after checking the number, the do-not-call list, calling hours and the wallet; the result arrives as the `call.completed` webhook (keys pressed included; `call.*` webhooks are sent for campaign and API-placed calls only) or `GET /api/v3/calls/{id}`. Placing needs `calls.place` on the key's issuer; reading needs `calls.history.view` (transcripts `calls.transcripts.view`, recordings `calls.recordings.view`), and the key sees the calls its issuer sees. A key issued with scopes also needs `calls:read` / `calls:write`."
        },
        {
            "name": "Call campaigns",
            "description": "Call a list of people with a message and keys (\"press 1 to confirm\"), an AI agent or an IVR flow, inside calling hours, with retries, a do-not-call list and the money held up front. The body is the campaign composer payload \u2014 the same shape the web composer, MCP and Automations use. Integrations add people with their own details and `external_id` (echoed on every result and webhook), from a Daftari table filter or lead stages, and can keep an always-on campaign open (`advanced.is_rolling`) that calls each new order. Results per person come from `GET \u2026/targets` and the `call_campaign.*` webhooks. Reading needs `call-campaigns.view`, creating `call-campaigns.create`, steering and adding people `call-campaigns.manage`. A key issued with scopes also needs `call_campaigns:read` / `call_campaigns:write`."
        },
        {
            "name": "MCP",
            "description": "The same account, the same permissions, reached by a language model instead of by your own code.\n\nMCP \u2014 the Model Context Protocol \u2014 is not a REST API, and this document does not pretend that it is. One MCP server is **one HTTP endpoint** speaking JSON-RPC 2.0: the operation is the `method` in the body rather than the URL, the tools are discovered at runtime with `tools/list`, and each tool's arguments are a JSON Schema rather than path, query and body parameters.\n\nWriting 348 tools as 348 near-identical `POST` operations would validate perfectly and teach nobody anything. So what is documented under this tag is the **transport** \u2014 the 31 servers' endpoints, the envelope, the OAuth handshake and where the tool contract lives. The tool contract itself is `GET /api-docs/mcp.json`, which carries a full JSON Schema per tool and is generated from the same code as this section.\n\n## Which one should I use\n\n**The REST API** when your own code drives the interaction \u2014 a cron job, a webhook handler, your backend. You know before you deploy which call you want to make, so a fixed contract is exactly what you want.\n\n**MCP** when a language model drives it \u2014 Claude, ChatGPT, or an agent you built. It chooses the call at runtime from what `tools/list` told it, which is only possible because the tool list is negotiated rather than compiled in.\n\nThey reach the same data and enforce the same permissions. What differs is who is holding the wheel.\n\n## Where each REST tag lands in MCP\n\n| REST tag | MCP server | Endpoint |\n|---|---|---|\n| Authentication | `account` | `/mcp/v1/account` |\n| SMS | `messaging` | `/mcp/v1/messaging` |\n| WhatsApp | `messaging`, `inbox` | `/mcp/v1/messaging`, `/mcp/v1/inbox` |\n| WhatsApp groups | `groups` | `/mcp/v1/groups` |\n| WhatsApp templates | `messaging` | `/mcp/v1/messaging` |\n| Contacts | `contacts` | `/mcp/v1/contacts` |\n| Catalogue | `shop`, `orders` | `/mcp/v1/shop`, `/mcp/v1/orders` |\n| Profile & Balance | `overview`, `account` | `/mcp/v1/overview`, `/mcp/v1/account` |\n| Webhooks | \u2014 | \u2014 |\n\n**Webhooks have no MCP equivalent, and will not.** MCP is request/response with the model asking; Momo Business calling *you* when something happens stays an HTTP callback.\n\nReachable only over MCP today: `ivr`, `flows`, `forms`, `data`, `approvals`, `payments`, `automations`, `alerts`, `operations`, `studio`, `numbers`, `agents`, `tickets`, `kb`, `content`, `calls`, `routing`, `meetings`, `comments`, `posts`, `leads`, `accounts`, `navigate`.\n\n## Authenticating\n\nTwo credentials reach the same endpoints, and both resolve to the account's identity narrowed to what was actually granted.\n\n- **`Authorization: Bearer momo_mcp_\u2026`** \u2014 an MCP connection from Dashboard \u2192 Settings \u2192 API credentials. For Claude Code, Claude Desktop, a self-hosted agent or curl. A v3 API key is refused here: same table, very different blast radius.\n- **OAuth 2.1 with dynamic client registration** \u2014 for claude.ai and ChatGPT, which have nowhere to paste a static token. Discovery, registration, authorization code with PKCE (S256), then the same bearer header.\n\nScopes come in two kinds, and the split *is* the safety model: a **capability** says which part of the business, an **elevation** says how far \u2014 publish, send, spend, delete, and for the data tables write and shape \u2014 and crosses every capability granted.\n\n| Scope | Grants | On the consent screen |\n|---|---|---|\n| `mcp:overview` | Overview and analytics | ticked |\n| `mcp:calls` | Calls | ticked |\n| `mcp:routing` | Call routing | off |\n| `mcp:numbers` | Phone numbers | off |\n| `mcp:meetings` | Meetings | off |\n| `mcp:builders` | Call flows and chat flows | off |\n| `mcp:data` | Data tables | off |\n| `mcp:studio` | Voice and audio | off |\n| `mcp:contacts` | Contacts | ticked |\n| `mcp:agents` | AI agents | off |\n| `mcp:commerce` | Orders and shop | off |\n| `mcp:support` | Support tickets | ticked |\n| `mcp:accounts` | Connected accounts | ticked |\n| `mcp:approvals` | Approvals | off |\n| `mcp:payments` | Payments | off |\n| `mcp:automations` | Automations | off |\n| `mcp:alerts` | Alerts and service levels | off |\n| `mcp:operations` | Operations | off |\n| `mcp:navigate` | Finding things | ticked |\n| `mcp:messaging` | Messaging | off |\n| `mcp:inbox` | Inbox | off |\n| `mcp:comments` | Comments | off |\n| `mcp:posts` | Posts | off |\n| `mcp:leads` | Leads | off |\n| `mcp:groups` | WhatsApp groups | off |\n| `mcp:publish` | Publish things | never ticked |\n| `mcp:send` | Send messages and place calls | never ticked |\n| `mcp:spend` | Start purchases and ask customers to pay | never ticked |\n| `mcp:delete` | Delete things | never ticked |\n| `mcp:write` | Save and change records | never ticked |\n| `mcp:shape` | Change tables and fields | never ticked |\n| `mcp:automate` | Set up things that run without you | never ticked |\n| `mcp:approve` | Answer approvals for you | never ticked |\n\nWhatever is granted is still intersected with what the consenting person can do. Scopes are a request; permissions are the ceiling.",
            "externalDocs": {
                "description": "The tool manifest \u2014 every server, every tool, a JSON Schema each.",
                "url": "https://business.momo.tz/api-docs/mcp.json"
            },
            "x-generated-by": "php artisan mcp:manifest",
            "x-mcp-servers": [
                {
                    "key": "ivr",
                    "name": "IVR",
                    "description": "Build and edit call flows: read the graph, apply node operations, validate, simulate, version and assign to numbers.",
                    "path": "/mcp/v1/ivr",
                    "module": "calls"
                },
                {
                    "key": "flows",
                    "name": "Message flows",
                    "description": "Build and edit WhatsApp conversation flows: nodes, edges, triggers, validation, simulation and analytics.",
                    "path": "/mcp/v1/flows",
                    "module": "flows"
                },
                {
                    "key": "forms",
                    "name": "WhatsApp forms",
                    "description": "Forms customers fill in inside WhatsApp: build them, check them with WhatsApp, publish, send to a customer, and read the answers.",
                    "path": "/mcp/v1/forms",
                    "module": "forms"
                },
                {
                    "key": "data",
                    "name": "Data tables",
                    "description": "The tables this business defined for itself and their records: read with filters, create/update/upsert rows, shape fields, run and save reports, and group related tables into folders with reports that read across them. Flows and IVRs read the same tables.",
                    "path": "/mcp/v1/data",
                    "module": "data"
                },
                {
                    "key": "approvals",
                    "name": "Approvals",
                    "description": "Decisions a person has been asked for before something happens: read the queue, read one in full with every comment on it, answer one.",
                    "path": "/mcp/v1/approvals",
                    "module": "approvals"
                },
                {
                    "key": "payments",
                    "name": "Payments",
                    "description": "Money this business collects from its customers: what has been asked for and where each one got to, one payment's whole timeline, asking a customer to pay, and refunds. Not the business's own Momo bill.",
                    "path": "/mcp/v1/payments",
                    "module": "payments"
                },
                {
                    "key": "automations",
                    "name": "Automations",
                    "description": "What happens without anybody there: the log of what has actually happened in the business, the subscriptions that react to it, and the schedules that run on a rhythm.",
                    "path": "/mcp/v1/automations",
                    "module": "automations"
                },
                {
                    "key": "alerts",
                    "name": "Alerts & service levels",
                    "description": "The business watching itself: the alert rules it wrote, the service-level promises and the clocks running against them, the risk rules that hold or refuse an action, and one log of everything that fired \u2014 including what reached nobody.",
                    "path": "/mcp/v1/alerts",
                    "module": "alerts"
                },
                {
                    "key": "operations",
                    "name": "Operations",
                    "description": "The named things this business can do \u2014 create a booking, register a customer, process a refund \u2014 each written down once, and the log of every time one ran.",
                    "path": "/mcp/v1/operations",
                    "module": "operations"
                },
                {
                    "key": "studio",
                    "name": "Studio",
                    "description": "Voice and audio: browse the voice library, generate speech, convert audio and publish it for use in an IVR.",
                    "path": "/mcp/v1/studio",
                    "module": null
                },
                {
                    "key": "numbers",
                    "name": "Numbers",
                    "description": "Phone numbers: what you own, what is available, what one costs, and how to pay for it.",
                    "path": "/mcp/v1/numbers",
                    "module": "calls"
                },
                {
                    "key": "groups",
                    "name": "WhatsApp groups",
                    "description": "Groups the business runs from its WhatsApp number: create, invite, post, approve joins, remove members.",
                    "path": "/mcp/v1/groups",
                    "module": "groups"
                },
                {
                    "key": "agents",
                    "name": "Agents",
                    "description": "Your own AI specialists: see the roster and ask one a question.",
                    "path": "/mcp/v1/agents",
                    "module": null
                },
                {
                    "key": "orders",
                    "name": "Orders",
                    "description": "Customer orders across every platform: find, read, move status, request payment.",
                    "path": "/mcp/v1/orders",
                    "module": "catalogue"
                },
                {
                    "key": "shop",
                    "name": "Shop",
                    "description": "Products, their sizes and add-ons, brands and categories, plus the order tools.",
                    "path": "/mcp/v1/shop",
                    "module": "catalogue"
                },
                {
                    "key": "tickets",
                    "name": "Tickets",
                    "description": "Support tickets: create, update, assign, reply, labels and notifications.",
                    "path": "/mcp/v1/tickets",
                    "module": null
                },
                {
                    "key": "kb",
                    "name": "Knowledge base",
                    "description": "Your knowledge base: categories, search and full article text.",
                    "path": "/mcp/v1/kb",
                    "module": null
                },
                {
                    "key": "content",
                    "name": "Platform content",
                    "description": "Public help articles, changelog, roadmap and system status.",
                    "path": "/mcp/v1/content",
                    "module": null
                },
                {
                    "key": "calls",
                    "name": "Calls",
                    "description": "Call history, recordings, transcripts, events and Call Studio scripts.",
                    "path": "/mcp/v1/calls",
                    "module": "calls"
                },
                {
                    "key": "routing",
                    "name": "Call routing",
                    "description": "Routing rules, ring groups, working hours and forwarding targets.",
                    "path": "/mcp/v1/routing",
                    "module": "calls"
                },
                {
                    "key": "meetings",
                    "name": "Meetings",
                    "description": "See and schedule meetings, and invite people to them.",
                    "path": "/mcp/v1/meetings",
                    "module": "calls"
                },
                {
                    "key": "messaging",
                    "name": "Messaging",
                    "description": "Templates, sender IDs, campaigns, message history \u2014 and sending SMS and WhatsApp.",
                    "path": "/mcp/v1/messaging",
                    "module": "marketing"
                },
                {
                    "key": "inbox",
                    "name": "Inbox",
                    "description": "Customer conversations across WhatsApp, SMS, social and email \u2014 read, assign, reply, and send new mail.",
                    "path": "/mcp/v1/inbox",
                    "module": "inbox"
                },
                {
                    "key": "comments",
                    "name": "Comments",
                    "description": "Comments on your Facebook, Instagram and TikTok posts.",
                    "path": "/mcp/v1/comments",
                    "module": "comments"
                },
                {
                    "key": "posts",
                    "name": "Posts",
                    "description": "Social posts to Facebook, Instagram, TikTok, YouTube and LinkedIn: what is drafted, scheduled and sent; drafting a new one; scheduling or publishing it.",
                    "path": "/mcp/v1/posts",
                    "module": "posts"
                },
                {
                    "key": "contacts",
                    "name": "Contacts",
                    "description": "The contact book and groups.",
                    "path": "/mcp/v1/contacts",
                    "module": "contacts"
                },
                {
                    "key": "leads",
                    "name": "Leads",
                    "description": "Every potential customer at any stage: find a person's lead by any number or id, add or update one without duplicating, move its stage, label it, note what was said, and give it to someone to follow up.",
                    "path": "/mcp/v1/leads",
                    "module": "leads"
                },
                {
                    "key": "overview",
                    "name": "Overview",
                    "description": "The dashboard, business analytics, call stats and spend \u2014 how the business is doing.",
                    "path": "/mcp/v1/overview",
                    "module": null
                },
                {
                    "key": "accounts",
                    "name": "Connected accounts",
                    "description": "The WhatsApp numbers, social profiles, mailboxes and SMS routes this business has connected, and what each can actually do.",
                    "path": "/mcp/v1/accounts",
                    "module": null
                },
                {
                    "key": "navigate",
                    "name": "Finding things",
                    "description": "Where pages and settings live in the app, and what each form asks for.",
                    "path": "/mcp/v1/navigate",
                    "module": null
                },
                {
                    "key": "account",
                    "name": "Account",
                    "description": "A cross-domain starting point: overview, search, fetch, and the most-used read tools.",
                    "path": "/mcp/v1/account",
                    "module": null
                }
            ],
            "x-rest-tag-map": {
                "Authentication": [
                    "account"
                ],
                "SMS": [
                    "messaging"
                ],
                "WhatsApp": [
                    "messaging",
                    "inbox"
                ],
                "WhatsApp groups": [
                    "groups"
                ],
                "WhatsApp templates": [
                    "messaging"
                ],
                "Contacts": [
                    "contacts"
                ],
                "Catalogue": [
                    "shop",
                    "orders"
                ],
                "Profile & Balance": [
                    "overview",
                    "account"
                ],
                "Webhooks": []
            }
        }
    ],
    "components": {
        "securitySchemes": {
            "BearerToken": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "tenant_api_token",
                "description": "A tenant API token from Dashboard \u2192 Settings \u2192 API Keys. Send it as `Authorization: Bearer <token>` on every request."
            },
            "McpBearerToken": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "momo_mcp",
                "description": "An MCP credential from Dashboard \u2192 Settings \u2192 API credentials \u2192 MCP connections. For Claude Code, Claude Desktop, a self-hosted agent, or curl. A v3 API key is **not** accepted here.",
                "x-generated-by": "php artisan mcp:manifest"
            },
            "McpOAuth": {
                "type": "oauth2",
                "description": "For hosted clients \u2014 claude.ai, ChatGPT \u2014 which have nowhere to paste a static token. Register with RFC 7591 dynamic client registration, then run authorization code + PKCE (S256). The account holder chooses the scopes on our consent screen, and whatever is granted is still intersected with what that person can actually do.",
                "flows": {
                    "authorizationCode": {
                        "authorizationUrl": "https://business.momo.tz/oauth/authorize",
                        "tokenUrl": "https://business.momo.tz/oauth/token",
                        "refreshUrl": "https://business.momo.tz/oauth/token",
                        "scopes": {
                            "mcp:overview": "How the business is doing \u2014 calls, messages, spend, and what needs attention.",
                            "mcp:calls": "Call history, recordings, transcripts and Call Studio scripts.",
                            "mcp:routing": "Routing rules, ring groups, working hours and forwarding targets.",
                            "mcp:numbers": "What you own, what is available, what one costs, and how it is configured.",
                            "mcp:meetings": "See and schedule meetings, and invite people to them.",
                            "mcp:builders": "Build and edit your IVRs and WhatsApp conversation flows \u2014 as drafts.",
                            "mcp:data": "The tables your business defined for itself \u2014 read records, save them, shape fields, run reports \u2014 and the business rules (limits, fees, eligibility, opening hours) your flows enforce. Flows and IVRs read the same tables and the same rules.",
                            "mcp:studio": "Voices, and generating spoken prompts for your call flows.",
                            "mcp:contacts": "Your contact book and groups.",
                            "mcp:agents": "Your AI agents, what they know, how they behave, and what they have done.",
                            "mcp:commerce": "Customer orders, products, brands and categories.",
                            "mcp:support": "Tickets and your knowledge base.",
                            "mcp:accounts": "Which WhatsApp numbers, social profiles and mailboxes are connected, and what each can do.",
                            "mcp:approvals": "Decisions people in your business are waiting on \u2014 what is pending, what was decided, and why. Answering one is separate.",
                            "mcp:payments": "Money your customers pay you: what has been asked for, what arrived, and each payment's history. Asking for money and refunding it need the spending tick as well.",
                            "mcp:automations": "What your business has set up to happen on its own \u2014 what reacts to an event, what runs on a rhythm, and a log of what actually fired. Changing any of it is separate.",
                            "mcp:alerts": "How your business watches itself: what it has asked to be told about, how quickly it promises to do things, what it checks before letting something through, and a log of everything that fired \u2014 including anything that reached nobody. Changing any of it is separate.",
                            "mcp:operations": "The named things your business can do \u2014 create a booking, register a customer, process a refund. Seeing what they are is included; DOING one needs the ticks its own steps call for.",
                            "mcp:navigate": "Where pages and settings live in the app, so it can point you to them.",
                            "mcp:messaging": "Templates, sender IDs, campaigns and your message history. Sending is separate.",
                            "mcp:inbox": "Read your customer conversations across WhatsApp, SMS, social and email.",
                            "mcp:comments": "Read comments on your Facebook, Instagram and TikTok posts.",
                            "mcp:posts": "Read what the business has drafted, scheduled and published on its social accounts. Drafting, scheduling and publishing are separate.",
                            "mcp:leads": "Your sales leads: find, add and update them, move their stage, label and assign them.",
                            "mcp:groups": "Groups your business runs from its WhatsApp number.",
                            "mcp:publish": "Make a call flow answer real calls, a chat flow reach real customers, or a routing change go live.",
                            "mcp:send": "Send an SMS, WhatsApp or email to a real person, reply to a customer, or ring a phone.",
                            "mcp:spend": "Begin buying a number or topping up, and ask your customers to pay you. You still approve every payment yourself, on your phone, and a refund still waits for somebody in your business to say yes.",
                            "mcp:delete": "Permanently remove flows, audio, contacts and tickets.",
                            "mcp:write": "Create, update and upsert rows in your data tables, and save reports.",
                            "mcp:shape": "Create tables, add, rename, retype or remove fields, put indexes and \"unique together\" rules on them, and arrange tables into groups. This changes what every screen and flow sees.",
                            "mcp:automate": "Create or change an automation: something that reacts to an event on its own, or runs on a rhythm \u2014 including sending your business's data to an address outside it.",
                            "mcp:approve": "Approve or reject a request somebody is waiting on \u2014 releasing a discount, a refund or a payout that was deliberately held for a person to sign off.",
                            "mcp:use": "The base grant every MCP token carries."
                        }
                    }
                },
                "x-generated-by": "php artisan mcp:manifest"
            }
        },
        "schemas": {
            "LegacyErrorEnvelope": {
                "type": "object",
                "required": [
                    "status",
                    "message"
                ],
                "description": "Error response envelope for validation and server errors.",
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "error"
                        ],
                        "description": "Always \"error\" for failure responses."
                    },
                    "message": {
                        "type": "string",
                        "description": "Human-readable error message."
                    },
                    "errors": {
                        "type": "object",
                        "description": "Optional field-level validation errors; keys are field names, values are arrays of messages.",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    },
                    "reason": {
                        "type": "string",
                        "description": "A machine-readable refusal code, where the endpoint has one. Leads: invalid, reason_required, won_locked, nothing_to_identify, assignee_unknown, ai_not_allowed."
                    }
                }
            },
            "RateLimitError": {
                "type": "object",
                "required": [
                    "status",
                    "message"
                ],
                "description": "Returned when the 120 requests/minute token limit is exceeded. Retry after the `Retry-After` header.",
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "error"
                        ],
                        "description": "Always \"error\"."
                    },
                    "message": {
                        "type": "string",
                        "description": "Human-readable rate limit message."
                    }
                }
            },
            "Pagination": {
                "type": "object",
                "required": [
                    "current_page",
                    "per_page",
                    "last_page",
                    "total",
                    "has_more_pages"
                ],
                "description": "Cursor-less pagination metadata for list endpoints.",
                "properties": {
                    "current_page": {
                        "type": "integer",
                        "description": "1-based current page index."
                    },
                    "per_page": {
                        "type": "integer",
                        "description": "Number of items per page."
                    },
                    "last_page": {
                        "type": "integer",
                        "description": "1-based index of the last page."
                    },
                    "total": {
                        "type": "integer",
                        "description": "Total number of items across all pages."
                    },
                    "has_more_pages": {
                        "type": "boolean",
                        "description": "True if more pages exist after the current page."
                    }
                }
            },
            "Message": {
                "type": "object",
                "required": [
                    "id",
                    "uid",
                    "direction",
                    "channel_type",
                    "recipient",
                    "body",
                    "status"
                ],
                "description": "SMS or WhatsApp message record with delivery and metadata fields.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Internal numeric id."
                    },
                    "uid": {
                        "type": "string",
                        "description": "Public unique identifier (e.g. msg_01JXYZSMS01)."
                    },
                    "direction": {
                        "type": "string",
                        "enum": [
                            "inbound",
                            "outbound"
                        ],
                        "description": "Whether you sent the message (`outbound`) or received it (`inbound`)."
                    },
                    "channel_type": {
                        "type": "string",
                        "enum": [
                            "sms",
                            "whatsapp"
                        ],
                        "description": "Channel: sms or whatsapp."
                    },
                    "tenant_channel_id": {
                        "type": "integer",
                        "description": "The account channel selected automatically by the outbound routing policy."
                    },
                    "channel_code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Resolved channel code returned for observability; it is not caller-selectable."
                    },
                    "sender": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Sender identity; inbound messages can contain the customer phone or provider identity."
                    },
                    "recipient": {
                        "type": "string",
                        "description": "Recipient phone number (E.164 or national)."
                    },
                    "body": {
                        "type": "string",
                        "description": "Message text content."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "processing",
                            "sent",
                            "checking_delivery",
                            "delivered",
                            "read",
                            "failed",
                            "received"
                        ],
                        "description": "Delivery status. Outbound messages walk queued \u2192 processing \u2192 sent \u2192 delivered \u2192 read, or stop at failed with `error_message` set; `received` is what inbound messages carry."
                    },
                    "media_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The attached file, when the message carries one."
                    },
                    "media_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The kind of attached media (image, video, audio, document, sticker)."
                    },
                    "gateway_message_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Provider message ID, used for replies/reactions. Customer message webhooks identify local records with numeric message_id instead."
                    },
                    "error_message": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the send failed, straight from the gateway. Null unless `status` is `failed`."
                    },
                    "metadata": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "additionalProperties": true,
                        "description": "Anything extra recorded with the message \u2014 the interactive or reaction payload, the id it replies to, the source that created it."
                    },
                    "template_params": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "additionalProperties": true,
                        "description": "The template name, language and variables used, when the message was sent from a template."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 8601 timestamp of when the message record was created."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 8601 timestamp of the last change to the record."
                    },
                    "sent_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the gateway accepted the message. Null until then."
                    },
                    "delivered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the gateway confirmed delivery to the recipient's device."
                    },
                    "read_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the recipient opened it. WhatsApp only, and only with read receipts on."
                    }
                }
            },
            "Campaign": {
                "type": "object",
                "required": [
                    "id",
                    "uid",
                    "name",
                    "status",
                    "channel_type",
                    "message"
                ],
                "description": "SMS campaign with recipient counts and status.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Internal numeric id."
                    },
                    "uid": {
                        "type": "string",
                        "description": "Public unique identifier."
                    },
                    "name": {
                        "type": "string",
                        "description": "Campaign name."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "draft",
                            "scheduled",
                            "running",
                            "paused",
                            "completed",
                            "cancelled"
                        ],
                        "description": "Campaign status. A campaign created without `schedule_time` starts as `draft` and begins immediately; one with a schedule waits in `scheduled`."
                    },
                    "channel_type": {
                        "type": "string",
                        "enum": [
                            "sms"
                        ],
                        "description": "Channel type; currently only sms."
                    },
                    "tenant_channel_id": {
                        "type": "integer",
                        "description": "The account channel selected automatically when the campaign was created."
                    },
                    "channel_code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Resolved channel code returned for observability; it is not caller-selectable."
                    },
                    "message": {
                        "type": "string",
                        "description": "Campaign message text."
                    },
                    "sender": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The sender identity the campaign sends from."
                    },
                    "scheduled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the campaign is due to start. Null for one that started immediately."
                    },
                    "total_recipients": {
                        "type": "integer",
                        "description": "How many contacts the campaign will send to."
                    },
                    "sent_count": {
                        "type": "integer",
                        "description": "How many have been sent so far."
                    },
                    "failed_count": {
                        "type": "integer",
                        "description": "How many the gateway refused."
                    },
                    "contact_group": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "Numeric group id."
                            },
                            "uid": {
                                "type": "string",
                                "description": "Group UUID \u2014 the form you can also pass as `contact_list_id`."
                            },
                            "name": {
                                "type": "string",
                                "description": "Group name as it appears in the dashboard."
                            }
                        },
                        "additionalProperties": false,
                        "description": "The contact group this campaign sends to."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 8601 timestamp of when the campaign was created."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 8601 timestamp of the last change to it."
                    }
                }
            },
            "Contact": {
                "type": "object",
                "required": [
                    "id",
                    "uid",
                    "group_id",
                    "group_uid",
                    "name",
                    "country_code",
                    "phone_number",
                    "full_phone_number",
                    "is_subscribed"
                ],
                "description": "Contact record within a group, with phone and optional custom fields.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Internal numeric id."
                    },
                    "uid": {
                        "type": "string",
                        "description": "Public unique identifier."
                    },
                    "group_id": {
                        "type": "integer",
                        "description": "Contact group internal id."
                    },
                    "group_uid": {
                        "type": "string",
                        "description": "Contact group public uid."
                    },
                    "name": {
                        "type": "string",
                        "description": "Contact display name."
                    },
                    "country_code": {
                        "type": "string",
                        "description": "Country code (e.g. 255)."
                    },
                    "phone_number": {
                        "type": "string",
                        "description": "National number without country code."
                    },
                    "full_phone_number": {
                        "type": "string",
                        "description": "E.164 or full number for sending."
                    },
                    "is_subscribed": {
                        "type": "boolean",
                        "description": "Stored subscription flag; not automatically applied by the current SMS campaign dispatch loop."
                    },
                    "custom_field_values": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Every non-reserved field you sent when creating or updating the contact, echoed back. Always an object \u2014 `{}` when there are none."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 8601 timestamp of when the contact was created."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 8601 timestamp of the last change to it."
                    }
                }
            },
            "Catalogue": {
                "type": "object",
                "description": "A shop: a set of products that can be shown to customers on WhatsApp.",
                "required": [
                    "id",
                    "name"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Catalogue id. Use it in every /catalogues/{catalogue} path."
                    },
                    "name": {
                        "type": "string",
                        "description": "Shop name as customers see it."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Optional shop description."
                    },
                    "vertical": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta commerce vertical, e.g. \"commerce\"."
                    },
                    "default_currency": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "ISO 4217 currency new products default to."
                    },
                    "sku_prefix": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The prefix on codes this shop issues itself, such as `AMY` in `AMY-00042`. Fixed once the shop exists."
                    },
                    "stock_policy": {
                        "type": "string",
                        "enum": [
                            "external",
                            "momo"
                        ],
                        "description": "`external`: your system owns the stock count, we mirror it and tell you what sold. `momo`: we keep the count, and orders reserve and commit against it. Shops created through this API default to `external`."
                    },
                    "source_of_truth": {
                        "type": "string",
                        "enum": [
                            "api",
                            "momo",
                            "platform"
                        ],
                        "description": "Who wins on product fields when a selling platform has drifted from us."
                    },
                    "allow_backorder": {
                        "type": "boolean",
                        "description": "Sell past zero. When false, a count of zero sets availability to `out of stock`."
                    },
                    "reservation_ttl_hours": {
                        "type": "integer",
                        "description": "How long a pending order holds stock before it goes back on the shelf."
                    },
                    "low_stock_threshold": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Raise `stock.low` at or below this count. Null means never."
                    },
                    "meta_catalogue_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta catalogue id when the shop is connected; null keeps every product local."
                    },
                    "is_connected_to_waba": {
                        "type": "boolean",
                        "description": "True once the shop is bound to a WhatsApp Business Account."
                    },
                    "is_catalogue_visible": {
                        "type": "boolean",
                        "description": "Whether customers can browse the catalogue in the chat."
                    },
                    "is_cart_enabled": {
                        "type": "boolean",
                        "description": "Whether customers can build a cart and submit an order."
                    },
                    "channels": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/CatalogueChannel"
                        },
                        "description": "Where this shop is published. Empty is normal for a shop that sells only through the assistant or the phone menus."
                    },
                    "products_count": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Number of products in the shop."
                    },
                    "orders_count": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Number of orders received by the shop."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the shop last synced to Meta."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601 creation timestamp."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601 update timestamp."
                    }
                }
            },
            "Product": {
                "type": "object",
                "description": "One product inside a catalogue. Prices are integers in the minor unit of `currency` (2500000 = TZS 25,000.00 for a 2-decimal currency).",
                "required": [
                    "id",
                    "retailer_id",
                    "name",
                    "price",
                    "currency"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Product id."
                    },
                    "catalogue_id": {
                        "type": "integer",
                        "description": "Catalogue this product belongs to."
                    },
                    "sku": {
                        "type": "string",
                        "description": "Your product code, and the identity this API addresses a product by. The shop issues one (`AMY-00042`) when you send none, and it is frozen once the product is live on any platform."
                    },
                    "retailer_id": {
                        "type": "string",
                        "description": "The older name for `sku`, kept in step with it. Prefer `sku` in new code."
                    },
                    "meta_product_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta product id once mirrored; null for a local-only product."
                    },
                    "name": {
                        "type": "string",
                        "description": "Product name (max 100 characters)."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Long description (max 5000 characters)."
                    },
                    "url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Link to the product page on your own site."
                    },
                    "price": {
                        "type": "integer",
                        "description": "Price in the minor unit of `currency`."
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO 4217 currency code."
                    },
                    "sale_price": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Optional sale price in the minor unit."
                    },
                    "image_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Publicly reachable product image. Meta fetches it directly."
                    },
                    "availability": {
                        "type": "string",
                        "enum": [
                            "in stock",
                            "out of stock",
                            "preorder",
                            "available for order",
                            "discontinued"
                        ],
                        "description": "Stock state."
                    },
                    "condition": {
                        "type": "string",
                        "enum": [
                            "new",
                            "refurbished",
                            "used"
                        ],
                        "description": "Product condition."
                    },
                    "brand": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Brand name."
                    },
                    "category": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Category label."
                    },
                    "product_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your own product taxonomy string."
                    },
                    "inventory": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Stock count."
                    },
                    "visibility": {
                        "type": "string",
                        "enum": [
                            "staging",
                            "published"
                        ],
                        "description": "Whether customers can see it."
                    },
                    "review_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta review outcome: pending, approved or rejected."
                    },
                    "sync_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "pending",
                            "syncing",
                            "synced",
                            "failed",
                            "blocked",
                            "drifted",
                            null
                        ],
                        "description": "A roll-up of `listings`. A product on a shop with no platforms is `synced`, because there is nothing to sync."
                    },
                    "listings": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ProductListing"
                        },
                        "description": "One row per platform this shop sells on."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the product last synced to Meta."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601 creation timestamp."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601 update timestamp."
                    }
                }
            },
            "OrderItem": {
                "type": "object",
                "description": "One line of a customer order, exactly as WhatsApp reported it.",
                "properties": {
                    "product_retailer_id": {
                        "type": "string",
                        "description": "The SKU the customer added to the cart."
                    },
                    "quantity": {
                        "type": "integer",
                        "description": "How many."
                    },
                    "item_price": {
                        "type": "integer",
                        "description": "Unit price in the minor unit of `currency`."
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO 4217 currency code."
                    },
                    "unit_price_minor": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Unit price in the minor unit. Prefer this over `item_price`, which is Meta's own field and is in MAJOR units."
                    },
                    "line_total_minor": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Unit price times quantity, in the minor unit."
                    },
                    "reserved": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How many units of this line are actually being held for the order."
                    },
                    "stock_short": {
                        "type": [
                            "boolean",
                            "null"
                        ],
                        "description": "True when we could not hold the whole quantity. The order was still recorded."
                    },
                    "unresolved": {
                        "type": [
                            "boolean",
                            "null"
                        ],
                        "description": "True when this product code is not in the catalogue. The code is kept verbatim so a person can work out what the customer meant."
                    }
                }
            },
            "Order": {
                "type": "object",
                "description": "An order a customer submitted from a WhatsApp cart.",
                "required": [
                    "id",
                    "customer_wa_id",
                    "status"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Order id."
                    },
                    "catalogue_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Catalogue the cart was built from."
                    },
                    "catalogue": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Compact catalogue reference.",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "Catalogue id."
                            },
                            "name": {
                                "type": "string",
                                "description": "Catalogue name."
                            }
                        }
                    },
                    "platform": {
                        "type": "string",
                        "description": "Where the order came from: `whatsapp`, `storefront`, `instagram`, `ivr`, `manual` and so on."
                    },
                    "customer_handle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Whatever identifies the customer on their own platform \u2014 a WhatsApp id, a handle, an email, a typed phone number."
                    },
                    "customer_wa_id": {
                        "type": "string",
                        "description": "The older name for `customer_handle`. It has not held only WhatsApp ids since orders became platform-neutral; prefer `customer_handle`."
                    },
                    "customer_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "WhatsApp profile name, when shared."
                    },
                    "customer_phone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Phone number when it differs from the WhatsApp id."
                    },
                    "customer_note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Free text the customer attached to the order."
                    },
                    "product_items": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OrderItem"
                        },
                        "description": "The cart lines."
                    },
                    "total_amount": {
                        "type": "integer",
                        "description": "Order total in the minor unit of `total_currency`."
                    },
                    "total_currency": {
                        "type": "string",
                        "description": "ISO 4217 currency code."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "confirmed",
                            "processing",
                            "shipped",
                            "delivered",
                            "cancelled",
                            "refunded"
                        ],
                        "description": "Fulfilment state."
                    },
                    "needs_attention": {
                        "type": "boolean",
                        "description": "Somebody has to look at this before it can be fulfilled: a line we could not hold stock for, or a product code that is not in the catalogue. The order still exists \u2014 a customer asked for it \u2014 and the offending line says which of the two it is."
                    },
                    "gateway_message_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "WhatsApp message id the order arrived on."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601 creation timestamp."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "ISO 8601 update timestamp."
                    }
                }
            },
            "WebhookEvent": {
                "type": "object",
                "properties": {
                    "event": {
                        "type": "string",
                        "description": "Event name. The full list with a sample payload each is at `GET /api/v3/webhooks/events`; the dashboard picker and this enum both read the same catalogue.",
                        "enum": [
                            "message.received",
                            "message.sent",
                            "message.delivered",
                            "message.read",
                            "message.failed",
                            "message.echoed",
                            "message.updated",
                            "order.received",
                            "order.status_changed",
                            "order.cancelled",
                            "order.paid",
                            "sync.completed",
                            "stock.low",
                            "product.blocked",
                            "product.drifted",
                            "campaign.completed",
                            "campaign.failed",
                            "group.created",
                            "group.create_failed",
                            "group.updated",
                            "group.deleted",
                            "group.suspended",
                            "group.suspension_cleared",
                            "group.participant_joined",
                            "group.participant_left",
                            "group.participant_removed",
                            "group.join_requested",
                            "group.join_request_revoked",
                            "group.invite_sent",
                            "template.status_changed",
                            "form.submitted",
                            "form.status_changed",
                            "webhook.paused",
                            "cart.submitted",
                            "cart.abandoned",
                            "flow.session.started",
                            "flow.session.ended",
                            "lead.created",
                            "lead.updated",
                            "lead.stage_changed",
                            "lead.label_added",
                            "lead.label_removed",
                            "lead.note_added",
                            "lead.assigned",
                            "lead.merged",
                            "lead.deleted",
                            "voice.otp.answered",
                            "voice.otp.completed",
                            "voice.otp.failed",
                            "voice.message.answered",
                            "voice.message.completed",
                            "voice.message.failed",
                            "call.completed",
                            "call.recording_ready",
                            "call.feedback_ready",
                            "call_campaign.started",
                            "call_campaign.target_completed",
                            "call_campaign.paused",
                            "call_campaign.resumed",
                            "call_campaign.completed",
                            "call_campaign.failed",
                            "webhook.test"
                        ]
                    },
                    "timestamp": {
                        "type": "string",
                        "description": "Dispatch time in ISO8601.",
                        "format": "date-time"
                    },
                    "message_id": {
                        "type": "integer",
                        "description": "Message events: local numeric message ID, usable in SMS/WhatsApp lookup."
                    },
                    "direction": {
                        "type": "string",
                        "description": "Message direction.",
                        "enum": [
                            "inbound",
                            "outbound"
                        ]
                    },
                    "sender": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Message sender identity."
                    },
                    "recipient": {
                        "type": "string",
                        "description": "Message recipient identity."
                    },
                    "status": {
                        "type": "string",
                        "description": "Message delivery state."
                    },
                    "body": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Message body."
                    },
                    "media_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Attached media URL."
                    },
                    "channel_type": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Message channel type."
                    },
                    "order_id": {
                        "type": "integer",
                        "description": "Order events: local order ID."
                    },
                    "customer_wa_id": {
                        "type": "string",
                        "description": "order.received: customer WhatsApp identifier."
                    },
                    "customer_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "order.received: customer name."
                    },
                    "product_items": {
                        "type": "array",
                        "description": "order.received: incoming cart items.",
                        "items": {
                            "$ref": "#/components/schemas/OrderItem"
                        }
                    },
                    "total_amount": {
                        "type": "integer",
                        "description": "order.received: total in integer hundredths."
                    },
                    "total_currency": {
                        "type": "string",
                        "description": "order.received: currency code."
                    },
                    "customer_note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "order.received: customer note."
                    },
                    "conversation_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Order event: linked conversation ID."
                    },
                    "created_at": {
                        "type": "string",
                        "description": "order.received: creation time.",
                        "format": "date-time"
                    },
                    "payment_id": {
                        "type": "integer",
                        "description": "order.paid: payment ID."
                    },
                    "method": {
                        "type": "string",
                        "description": "order.paid: payment method."
                    },
                    "amount_minor": {
                        "type": "integer",
                        "description": "order.paid: paid amount in minor units."
                    },
                    "currency": {
                        "type": "string",
                        "description": "order.paid: currency code."
                    },
                    "payer_msisdn": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "order.paid: payer phone number."
                    },
                    "paid_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "order.paid: settlement time.",
                        "format": "date-time"
                    },
                    "group": {
                        "$ref": "#/components/schemas/WhatsAppGroup",
                        "description": "Current local WhatsApp group summary, when the event concerns a group."
                    },
                    "wa_ids": {
                        "type": "array",
                        "description": "Participant event: affected WhatsApp IDs.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Participant event reason when supplied. lead.stage_changed: the reason given for lost or unqualified."
                    },
                    "applied": {
                        "type": "object",
                        "description": "group.updated: applied settings.",
                        "additionalProperties": true
                    },
                    "errors": {
                        "type": [
                            "array",
                            "object",
                            "null"
                        ],
                        "description": "Provider/group error details.",
                        "items": [],
                        "additionalProperties": true
                    },
                    "sent": {
                        "type": [
                            "integer",
                            "array"
                        ],
                        "description": "group.invite_sent: successfully sent invitations.",
                        "items": []
                    },
                    "failed": {
                        "type": [
                            "integer",
                            "array"
                        ],
                        "description": "group.invite_sent: failed invitations.",
                        "items": []
                    },
                    "template_id": {
                        "type": "integer",
                        "description": "template.status_changed: local template id, for `GET /api/v3/whatsapp/templates/{template}`."
                    },
                    "name": {
                        "type": "string",
                        "description": "template.status_changed: the template name."
                    },
                    "language": {
                        "type": "string",
                        "description": "template.status_changed: the template language."
                    },
                    "whatsapp_business_account_id": {
                        "type": "string",
                        "description": "template.status_changed: the WhatsApp Business Account whose review moved."
                    },
                    "whatsapp_template_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "template.status_changed: Meta's id on that account."
                    },
                    "previous_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "template.status_changed: the status before this change."
                    },
                    "whatsapp_status": {
                        "type": "string",
                        "description": "template.status_changed: the status now.",
                        "enum": [
                            "pending",
                            "in_review",
                            "approved",
                            "rejected",
                            "disabled",
                            "paused"
                        ]
                    },
                    "rejection_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "template.status_changed: Meta's reason when the new status is rejected."
                    },
                    "event_id": {
                        "type": "string",
                        "description": "This event's id: `evt_` + a ULID. The same on every retry and replay and on every endpoint that receives the event \u2014 dedupe on this (also sent as `X-Event-Id`)."
                    },
                    "lead": {
                        "$ref": "#/components/schemas/LeadWebhookSnapshot",
                        "description": "lead.* events: the whole lead as it is now."
                    },
                    "changes": {
                        "type": "object",
                        "description": "lead.updated, lead.stage_changed, lead.assigned: `{field: {from, to}}`. A burst of updates within about five seconds arrives as one lead.updated with the changes folded together.",
                        "additionalProperties": true
                    },
                    "actor": {
                        "type": "object",
                        "description": "lead.* events: who made the change.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "user, ai, mcp, api, flow, form, import or system."
                            },
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The person, AI agent or credential id, when there is one."
                            },
                            "label": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Their name at the time."
                            }
                        }
                    },
                    "source": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "lead.* events: the call or conversation the change happened in, if any.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "call, conversation, comment, form_answer, email or contact."
                            },
                            "id": {
                                "type": "string",
                                "description": "That record's id, as a string."
                            },
                            "channel": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Its channel."
                            }
                        }
                    },
                    "label": {
                        "type": "object",
                        "description": "lead.label_added / lead.label_removed: the label.",
                        "properties": {
                            "name": {
                                "type": "string",
                                "description": "Label name."
                            },
                            "color": {
                                "type": "string",
                                "description": "Hex colour."
                            }
                        }
                    },
                    "note": {
                        "type": "object",
                        "description": "lead.note_added: the note.",
                        "properties": {
                            "body": {
                                "type": "string",
                                "description": "The note text."
                            },
                            "author": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Who wrote it."
                            }
                        }
                    },
                    "merged_id": {
                        "type": "string",
                        "description": "lead.merged: the id of the lead that was merged into `lead` and no longer exists.",
                        "format": "uuid"
                    },
                    "test": {
                        "type": "boolean",
                        "description": "webhook.test and any sample sent with the Test button: true. Never set on a real event."
                    },
                    "message": {
                        "type": "string",
                        "description": "webhook.test: a sentence saying what this is."
                    },
                    "call": {
                        "$ref": "#/components/schemas/Call",
                        "description": "call.*: the call (the same object GET /api/v3/calls/{id} returns). call.* events are sent only for calls a call campaign or POST /api/v3/calls placed."
                    },
                    "campaign": {
                        "type": "object",
                        "description": "call_campaign.*: the campaign (the same object GET /api/v3/call-campaigns/{id} returns); on call_campaign.target_completed only its id, name, external_ref and is_rolling.",
                        "additionalProperties": true
                    },
                    "target": {
                        "$ref": "#/components/schemas/CallCampaignTarget",
                        "description": "call_campaign.target_completed: the person, echoing your external_id and variables."
                    },
                    "recording": {
                        "type": "object",
                        "description": "call.recording_ready: the recording.",
                        "properties": {
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The recording id."
                            },
                            "duration_seconds": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Length."
                            },
                            "status": {
                                "type": "string",
                                "description": "complete \u2026"
                            },
                            "list_url": {
                                "type": "string",
                                "description": "GET it with your key for the audio link."
                            }
                        }
                    },
                    "feedback": {
                        "type": "object",
                        "description": "call.feedback_ready: the AI's summary of the call.",
                        "properties": {
                            "summary": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "One-paragraph summary."
                            },
                            "sentiment": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "positive, neutral or negative."
                            },
                            "disposition": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "How the call ended, in the AI's words."
                            },
                            "key_topics": {
                                "type": "array",
                                "description": "Topics raised.",
                                "items": {
                                    "type": "string",
                                    "description": "A topic."
                                }
                            },
                            "action_items": {
                                "type": "array",
                                "description": "Things to do.",
                                "items": {
                                    "type": "string",
                                    "description": "An action."
                                }
                            },
                            "next_best_action": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "What to do next."
                            }
                        }
                    },
                    "answers": {
                        "type": "object",
                        "description": "call.feedback_ready on a campaign call: the person's answers so far.",
                        "additionalProperties": true
                    },
                    "state": {
                        "type": "string",
                        "description": "call_campaign.completed: finished (everyone called) or stopped (ended early)."
                    },
                    "automatic": {
                        "type": "boolean",
                        "description": "call_campaign.paused / .resumed: the campaign did it by itself (wallet low, needs attention, wallet topped up)."
                    },
                    "top_up": {
                        "type": "number",
                        "description": "call_campaign.paused with reason wallet_low: how much to top up to continue."
                    },
                    "attention_reason": {
                        "type": "string",
                        "description": "call_campaign.paused with reason needs_attention: caller_number_disabled, agent_deleted, ivr_unpublished, pbx_unreachable or message_invalid."
                    },
                    "campaign_uid": {
                        "type": "string",
                        "description": "campaign.completed / campaign.failed: the SMS campaign."
                    },
                    "recipients": {
                        "type": "integer",
                        "description": "campaign.completed: people the SMS campaign went to."
                    },
                    "channel": {
                        "type": "string",
                        "description": "campaign.completed / campaign.failed: sms or whatsapp."
                    }
                },
                "required": [
                    "event",
                    "timestamp"
                ],
                "description": "Actual flat ChannelWebhook payload. Every body carries `event`, `event_id` and `timestamp`. Message events include message_id/direction/sender/recipient/status/body/media_url/channel_type. Orders, groups and leads supply their own fields \u2014 a `lead.*` event carries the full `lead`, plus `changes`, `actor` and, when it happened in a call or chat, `source`. No data wrapper, tenant_id or occurred_at is added by this dispatcher."
            },
            "WhatsAppGroup": {
                "type": "object",
                "description": "A WhatsApp group the business number created. `id` is the platform id every endpoint takes; `meta_group_id` is WhatsApp's own id and is null while status is `creating`.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Platform id of the group; what every group endpoint takes."
                    },
                    "meta_group_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "WhatsApp's own group id. Null while the group is still being created."
                    },
                    "request_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "WhatsApp's create request id; how the confirmation webhook is matched."
                    },
                    "phone_number_id": {
                        "type": "string",
                        "description": "The business number the group was created from."
                    },
                    "waba_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The WhatsApp Business Account the number belongs to."
                    },
                    "subject": {
                        "type": "string",
                        "maxLength": 128,
                        "description": "The group name, up to 128 characters."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 2048,
                        "description": "What the group is for; members see it before joining. Up to 2048 characters."
                    },
                    "join_approval_mode": {
                        "type": "string",
                        "enum": [
                            "auto_approve",
                            "approval_required"
                        ],
                        "description": "auto_approve: anyone with the link joins. approval_required: the business approves each request."
                    },
                    "invite_link": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The chat.whatsapp.com link people tap to join. Null until WhatsApp confirms the group."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "creating",
                            "active",
                            "suspended",
                            "deleted",
                            "failed"
                        ],
                        "description": "creating (waiting for WhatsApp), active, suspended (by WhatsApp, for policy), deleted, or failed (WhatsApp refused to create it; see last_error)."
                    },
                    "participant_count": {
                        "type": "integer",
                        "description": "Members besides the business."
                    },
                    "max_participants": {
                        "type": "integer",
                        "description": "8, the business counted in."
                    },
                    "seats_left": {
                        "type": "integer",
                        "description": "How many more people can join."
                    },
                    "pending_join_requests": {
                        "type": "integer",
                        "description": "People waiting for approval on an approval_required group."
                    },
                    "conversation_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The inbox thread for the group."
                    },
                    "invite_template_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The approved template used for invites from this group."
                    },
                    "last_message_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the thread last had a message, either way."
                    },
                    "last_error": {
                        "type": [
                            "object",
                            "array",
                            "null"
                        ],
                        "description": "WhatsApp's last refusal, when there was one."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the roster and settings were last read back from WhatsApp."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the platform created the record."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it last changed."
                    }
                },
                "required": [
                    "id",
                    "subject",
                    "status",
                    "participant_count",
                    "max_participants"
                ]
            },
            "WhatsAppGroupParticipant": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Platform id of the group; what every group endpoint takes."
                    },
                    "wa_id": {
                        "type": "string",
                        "description": "The person, as WhatsApp identifies them (digits, international format)."
                    },
                    "display_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The name WhatsApp showed with their last message, when known."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "invited",
                            "member",
                            "left",
                            "removed",
                            "failed"
                        ],
                        "description": "creating (waiting for WhatsApp), active, suspended (by WhatsApp, for policy), deleted, or failed (WhatsApp refused to create it; see last_error)."
                    },
                    "invited_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the invite template was sent to them."
                    },
                    "joined_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When they joined."
                    },
                    "left_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When they left or were removed."
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "How they got here: invite_link, left, removed_by_business, sync, group_deleted."
                    },
                    "last_error": {
                        "type": [
                            "object",
                            "array",
                            "null"
                        ],
                        "description": "WhatsApp's last refusal, when there was one."
                    }
                }
            },
            "WhatsAppGroupJoinRequest": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Platform id of the group; what every group endpoint takes."
                    },
                    "join_request_id": {
                        "type": "string",
                        "description": "WhatsApp's id for the request; what approve and reject take."
                    },
                    "wa_id": {
                        "type": "string",
                        "description": "The person, as WhatsApp identifies them (digits, international format)."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "approved",
                            "rejected",
                            "revoked",
                            "failed"
                        ],
                        "description": "creating (waiting for WhatsApp), active, suspended (by WhatsApp, for policy), deleted, or failed (WhatsApp refused to create it; see last_error)."
                    },
                    "requested_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When they asked to join."
                    },
                    "resolved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the request was approved, rejected or withdrawn."
                    }
                }
            },
            "WhatsAppGroupEvent": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Platform id of the group; what every group endpoint takes."
                    },
                    "type": {
                        "type": "string",
                        "description": "What happened, e.g. group.participant_joined."
                    },
                    "actor": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "business",
                            "participant",
                            "meta",
                            "user",
                            null
                        ],
                        "description": "Who did it: business, participant, meta, or a user of this platform."
                    },
                    "payload": {
                        "type": [
                            "object",
                            "array",
                            "null"
                        ],
                        "description": "Event-specific detail."
                    },
                    "occurred_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it happened."
                    }
                }
            },
            "WhatsAppGroupDetail": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/WhatsAppGroup"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "participants": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/WhatsAppGroupParticipant"
                                },
                                "description": "Everyone ever invited into or seen in the group, with their current state."
                            },
                            "join_requests": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/WhatsAppGroupJoinRequest"
                                },
                                "description": "Join requests, newest first."
                            },
                            "invite_template": {
                                "type": [
                                    "object",
                                    "null"
                                ],
                                "properties": {
                                    "id": {
                                        "type": "integer",
                                        "description": "Platform id of the group; what every group endpoint takes."
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Template name."
                                    },
                                    "language": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "Template language code."
                                    },
                                    "whatsapp_status": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "The template's approval state on WhatsApp."
                                    }
                                },
                                "description": "Name of an approved group-invite template on this account."
                            },
                            "events": {
                                "type": "array",
                                "items": {
                                    "$ref": "#/components/schemas/WhatsAppGroupEvent"
                                },
                                "description": "Recent activity, newest first."
                            }
                        }
                    }
                ]
            },
            "DataTable": {
                "type": "object",
                "description": "A table as the list shows it.",
                "required": [
                    "id",
                    "name",
                    "slug",
                    "records_count",
                    "columns_count"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The table id; the `{table}` path parameter everywhere else."
                    },
                    "name": {
                        "type": "string",
                        "description": "Display name."
                    },
                    "slug": {
                        "type": "string",
                        "description": "URL-safe name, unique within the tenant."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the table holds, as written by whoever created it."
                    },
                    "icon": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Icon name chosen in the dashboard, or null."
                    },
                    "records_count": {
                        "type": "integer",
                        "description": "Live (not deleted) records in the table."
                    },
                    "columns_count": {
                        "type": "integer",
                        "description": "Columns defined on the table."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the table or its columns last changed (ISO-8601)."
                    }
                }
            },
            "DataTableDetail": {
                "type": "object",
                "description": "The table as the schema payload describes it: the list row plus storage, the title column and the creation time.",
                "required": [
                    "id",
                    "name",
                    "slug",
                    "records_count",
                    "storage_bytes"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The table id."
                    },
                    "name": {
                        "type": "string",
                        "description": "Display name."
                    },
                    "slug": {
                        "type": "string",
                        "description": "URL-safe name, unique within the tenant."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the table holds, or null."
                    },
                    "icon": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Icon name chosen in the dashboard, or null."
                    },
                    "records_count": {
                        "type": "integer",
                        "description": "Live (not deleted) records in the table."
                    },
                    "storage_bytes": {
                        "type": "integer",
                        "description": "Bytes the records occupy, counted against the storage quota."
                    },
                    "title_column": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Key of the column that names a record (the `title` on every record row), or null when the first text column is used."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the table was created (ISO-8601)."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the table or its columns last changed (ISO-8601)."
                    },
                    "retention": {
                        "type": "object",
                        "description": "Retention policy description.",
                        "additionalProperties": true
                    },
                    "legal_hold": {
                        "type": "boolean",
                        "description": "Whether retention deletion is held for this table."
                    }
                }
            },
            "DataColumn": {
                "type": "object",
                "description": "One column of a table: its key (the name to use in `data` and in filters), its type, the operators the type accepts in a filter, the validation rules a write runs, and display hints. A column whose type this version does not know comes back as `type: \"unknown\"` with a `warning`; its values are read-only.",
                "required": [
                    "id",
                    "key",
                    "label",
                    "type",
                    "position",
                    "required",
                    "unique",
                    "indexed",
                    "rules",
                    "operators",
                    "ui"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The column id."
                    },
                    "key": {
                        "type": "string",
                        "description": "The key this column has inside a record's `data`, and the `column` to name in a filter or a `sort`."
                    },
                    "label": {
                        "type": "string",
                        "description": "Display label."
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "text",
                            "long_text",
                            "number",
                            "currency",
                            "boolean",
                            "date",
                            "datetime",
                            "phone",
                            "email",
                            "select",
                            "multi_select",
                            "relation",
                            "file",
                            "auto_number",
                            "unknown"
                        ],
                        "description": "The field type. Its rules, operators and display hints are in `types` on the schema payload. `auto_number` is written by the platform: its `ui.readonly` is true and a value sent for it is refused."
                    },
                    "stored_type": {
                        "type": "string",
                        "description": "Only when `type` is `unknown`: the type name actually stored, which this version cannot render."
                    },
                    "position": {
                        "type": "integer",
                        "description": "Zero-based column order; record `data` keys come back in this order."
                    },
                    "required": {
                        "type": "boolean",
                        "description": "A create must supply a value; an update may not clear it."
                    },
                    "unique": {
                        "type": "boolean",
                        "description": "No two live records may share a value. A duplicate answers 422 with `errors`."
                    },
                    "indexed": {
                        "type": "boolean",
                        "description": "Whether the column has an index. Sorting a large table on a column needs one \u2014 see `sort_index_threshold`."
                    },
                    "index_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "pending",
                            "building",
                            "ready",
                            "failed",
                            "dropping",
                            null
                        ],
                        "description": "State of the latest index job on this column, or null when none was ever requested. Only `ready` makes the column sortable at scale."
                    },
                    "index_error": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the index build failed, when `index_status` is `failed`."
                    },
                    "config": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Type-specific settings: `options` for select/multi_select, `table_id` for relation, `default`, `ui` hints, and so on."
                    },
                    "rules": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The validation rules a write runs, Laravel-style (`required`, `phone:TZ`, `max:255`, \u2026)."
                    },
                    "operators": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "equals",
                                "not_equals",
                                "contains",
                                "starts_with",
                                "greater_than",
                                "less_than",
                                "between",
                                "is_empty",
                                "is_not_empty",
                                "in"
                            ]
                        },
                        "description": "The filter operators this column accepts. Any other operator answers 422."
                    },
                    "ui": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Display hints for a grid or form: `cell` and `input` renderer names, `filter` widget, `width` in pixels, plus any of `hidden_in_grid`, `hidden_in_form`, `help_text`, `placeholder`, `is_title_field` set in the dashboard.",
                        "properties": {
                            "cell": {
                                "type": "string",
                                "description": "Renderer for the value in a grid cell."
                            },
                            "input": {
                                "type": "string",
                                "description": "Renderer for the value in a form."
                            },
                            "filter": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Filter widget, or null when the column cannot be filtered."
                            },
                            "width": {
                                "type": "integer",
                                "description": "Suggested column width in pixels."
                            }
                        }
                    },
                    "warning": {
                        "type": "string",
                        "description": "Only when `type` is `unknown`: why the column is read-only."
                    }
                }
            },
            "DataFieldType": {
                "type": "object",
                "description": "What one field type can do, keyed by type name in the schema payload's `types`.",
                "required": [
                    "label",
                    "operators",
                    "ui",
                    "numeric",
                    "temporal"
                ],
                "properties": {
                    "label": {
                        "type": "string",
                        "description": "Display label of the type."
                    },
                    "operators": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "equals",
                                "not_equals",
                                "contains",
                                "starts_with",
                                "greater_than",
                                "less_than",
                                "between",
                                "is_empty",
                                "is_not_empty",
                                "in"
                            ]
                        },
                        "description": "The filter operators the type accepts."
                    },
                    "ui": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Default display hints for columns of this type (`cell`, `input`, `filter`, `width`).",
                        "properties": {
                            "cell": {
                                "type": "string",
                                "description": "Renderer for the value in a grid cell."
                            },
                            "input": {
                                "type": "string",
                                "description": "Renderer for the value in a form."
                            },
                            "filter": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Filter widget, or null."
                            },
                            "width": {
                                "type": "integer",
                                "description": "Suggested column width in pixels."
                            }
                        }
                    },
                    "numeric": {
                        "type": "boolean",
                        "description": "True for number and currency: `greater_than`, `less_than` and `between` compare as numbers."
                    },
                    "temporal": {
                        "type": "boolean",
                        "description": "True for date and datetime: filter values may be a `{\"relative\": \"<preset>\"}` window."
                    }
                }
            },
            "DataSystemColumn": {
                "type": "object",
                "description": "A column every table has without defining it. Filter and sort on it by its `$`-prefixed key.",
                "required": [
                    "key",
                    "label",
                    "type",
                    "operators"
                ],
                "properties": {
                    "key": {
                        "type": "string",
                        "enum": [
                            "$id",
                            "$created_at",
                            "$updated_at",
                            "$source"
                        ],
                        "description": "The key to use in a filter `column` or in `sort`."
                    },
                    "label": {
                        "type": "string",
                        "description": "Display label."
                    },
                    "type": {
                        "type": "string",
                        "description": "The field type its values behave as."
                    },
                    "operators": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "equals",
                                "not_equals",
                                "contains",
                                "starts_with",
                                "greater_than",
                                "less_than",
                                "between",
                                "is_empty",
                                "is_not_empty",
                                "in"
                            ]
                        },
                        "description": "The operators this system column accepts."
                    }
                }
            },
            "DataSchema": {
                "type": "object",
                "description": "Everything a client needs to read and write one table: the table, its columns, what each type can do, the system columns, quota usage and what this key may do. Re-fetch it after any column change in the dashboard.",
                "required": [
                    "table",
                    "columns",
                    "types",
                    "system_columns",
                    "limits",
                    "sort_index_threshold",
                    "can",
                    "access",
                    "actions",
                    "unique_sets"
                ],
                "properties": {
                    "table": {
                        "$ref": "#/components/schemas/DataTableDetail",
                        "description": "The table."
                    },
                    "columns": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataColumn"
                        },
                        "description": "The columns, in position order."
                    },
                    "types": {
                        "type": "object",
                        "additionalProperties": {
                            "$ref": "#/components/schemas/DataFieldType"
                        },
                        "description": "Every field type this version knows, keyed by name (`text`, `number`, `phone`, \u2026)."
                    },
                    "system_columns": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataSystemColumn"
                        },
                        "description": "The `$id`, `$created_at`, `$updated_at` and `$source` columns."
                    },
                    "limits": {
                        "type": "object",
                        "description": "Current table allowances and usage. Record/storage quota refusals use HTTP 402 with error.code quota_exceeded and quota/limit/used in error.details.",
                        "properties": {
                            "columns": {
                                "type": "object",
                                "description": "How many columns the table uses against its allowance.",
                                "properties": {
                                    "used": {
                                        "type": "integer",
                                        "description": "columns in use."
                                    },
                                    "max": {
                                        "type": "integer",
                                        "description": "The most columns this table may have."
                                    }
                                }
                            },
                            "indexes": {
                                "type": "object",
                                "description": "How many indexes the table uses against its allowance.",
                                "properties": {
                                    "used": {
                                        "type": "integer",
                                        "description": "indexes in use."
                                    },
                                    "max": {
                                        "type": "integer",
                                        "description": "The most indexes this table may have."
                                    }
                                }
                            },
                            "records": {
                                "type": "object",
                                "description": "How many records the table uses against its allowance.",
                                "properties": {
                                    "used": {
                                        "type": "integer",
                                        "description": "records in use."
                                    },
                                    "max": {
                                        "type": "integer",
                                        "description": "The most records this table may have."
                                    }
                                }
                            },
                            "storage": {
                                "type": "object",
                                "description": "Bytes the records occupy against the table's storage allowance.",
                                "properties": {
                                    "used_bytes": {
                                        "type": "integer",
                                        "description": "Bytes in use."
                                    },
                                    "max_bytes": {
                                        "type": "integer",
                                        "description": "The storage allowance in bytes."
                                    }
                                }
                            }
                        }
                    },
                    "sort_index_threshold": {
                        "type": "integer",
                        "description": "At or above this record count, sorting on an unindexed user column returns 501 not_supported with reason sort_needs_index. System timestamp sorts remain supported."
                    },
                    "can": {
                        "type": "object",
                        "description": "What the user who issued this key may do.",
                        "properties": {
                            "manage": {
                                "type": "boolean",
                                "description": "May change tables and columns (in the dashboard; not over this API)."
                            },
                            "edit_records": {
                                "type": "boolean",
                                "description": "May create, change and delete records \u2014 the gate on the write endpoints here."
                            },
                            "manage_reports": {
                                "type": "boolean",
                                "description": "May save reports on this table."
                            }
                        }
                    },
                    "access": {
                        "type": "object",
                        "description": "Per-table access for this caller, including governed state and granted capabilities.",
                        "additionalProperties": true
                    },
                    "actions": {
                        "type": "array",
                        "description": "Available record-action summaries, without private action secrets.",
                        "items": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    },
                    "unique_sets": {
                        "type": "array",
                        "description": "Unique field combinations and their index state.",
                        "items": {
                            "type": "object",
                            "additionalProperties": true
                        }
                    }
                }
            },
            "DataRecord": {
                "type": "object",
                "description": "One record: its values keyed by column key, who wrote it, when, and what names it.",
                "required": [
                    "id",
                    "data",
                    "source",
                    "created_at",
                    "updated_at",
                    "title"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The record id."
                    },
                    "data": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The values, keyed by column key, in column position order. A column with no value is absent or null."
                    },
                    "source": {
                        "type": "string",
                        "description": "Who created the record, fixed at create time: `ui` for a person in the dashboard, `api` for this API, a flow identifier for a flow. Filter on it with the `$source` system column."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the record was created \u2014 UTC, with microseconds, so a cursor built from it resumes at exactly this row."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the record last changed (UTC, microseconds)."
                    },
                    "title": {
                        "type": "string",
                        "description": "What names this record: the table's title column, else its first text column, else the id."
                    },
                    "titles": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "string"
                        },
                        "description": "Only on tables with relation columns: the related record's title keyed by the relation column key, resolved once per page so a client never fetches per cell."
                    }
                }
            },
            "DataRecordPage": {
                "type": "object",
                "description": "One keyset page of records.",
                "required": [
                    "records",
                    "next_cursor",
                    "has_more",
                    "count",
                    "served_at"
                ],
                "properties": {
                    "records": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataRecord"
                        },
                        "description": "The records on this page, in the requested sort order."
                    },
                    "next_cursor": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Opaque position of the last row served. Pass it back as `cursor` \u2014 with the same `filter`, `q`, `sort` and `dir` \u2014 for the next page. Null on the last page."
                    },
                    "has_more": {
                        "type": "boolean",
                        "description": "Whether another page follows."
                    },
                    "count": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Total records matching the filter and search \u2014 only when `with_count=1` was sent, otherwise null."
                    },
                    "served_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When this page was read (UTC). Records created after it are not on any later page of the same cursor chain when sorting `$created_at desc`."
                    }
                }
            },
            "DataCondition": {
                "type": "object",
                "description": "A filter, as a condition tree. A node is either a group \u2014 `{\"all\": [...]}` (AND) or `{\"any\": [...]}` (OR), nested up to 6 deep \u2014 or a leaf `{column, op, value}`. At most 40 leaves. An empty object is no filter.\n\n`column` is a column key from the schema, or a system column: `$id` (equals, in), `$created_at` / `$updated_at` (equals, not_equals, greater_than, less_than, between), `$source` (equals, in, starts_with). `op` must be one the column's type lists in `operators`, or the request answers 422.\n\n`value` follows the type: a scalar for equals/not_equals/contains/starts_with/greater_than/less_than, a list for `in` and for `between` (`[from, to]`), nothing for is_empty/is_not_empty. Values are validated and coerced through the column type first, so `phone equals 0712345678` matches the stored `+255712345678`. For date and datetime columns `value` may be `{\"relative\": \"<preset>\"}` \u2014 `today`, `yesterday`, `last_7_days`, `last_30_days`, `last_90_days`, `this_month`, `last_month` \u2014 with any temporal operator: equals/between = inside the window, greater_than = since its start, less_than = before its end. On `multi_select`, `contains` means has ANY of the listed options and `in` means has ALL.",
                "properties": {
                    "all": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataCondition"
                        },
                        "description": "Every child must match (AND)."
                    },
                    "any": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataCondition"
                        },
                        "description": "At least one child must match (OR)."
                    },
                    "column": {
                        "type": "string",
                        "description": "Leaf only: the column key, or a `$`-prefixed system column."
                    },
                    "op": {
                        "type": "string",
                        "enum": [
                            "equals",
                            "not_equals",
                            "contains",
                            "starts_with",
                            "greater_than",
                            "less_than",
                            "between",
                            "is_empty",
                            "is_not_empty",
                            "in"
                        ],
                        "description": "Leaf only: the operator. Must be one the column's type accepts."
                    },
                    "value": {
                        "description": "Leaf only: the value to compare with \u2014 a scalar, a list for `in`/`between`, a `{\"relative\": preset}` window on temporal columns, or omitted for `is_empty`/`is_not_empty`."
                    }
                }
            },
            "DataError": {
                "type": "object",
                "properties": {
                    "error": {
                        "$ref": "#/components/schemas/DataErrorDetails",
                        "description": "Structured domain refusal with a stable machine code and retry guidance."
                    },
                    "message": {
                        "type": "string",
                        "description": "Compatibility human message from the originating refusal."
                    },
                    "code": {
                        "type": "string",
                        "description": "Same category as error.code.",
                        "enum": [
                            "validation_error",
                            "conflict",
                            "not_found",
                            "rate_limited",
                            "quota_exceeded",
                            "temporary_failure",
                            "permission_denied",
                            "not_supported",
                            "provider_failure"
                        ]
                    },
                    "errors": {
                        "type": "object",
                        "description": "Optional field messages in Laravel validation shape.",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                },
                "required": [
                    "error",
                    "message",
                    "code"
                ],
                "description": "Expected refusal from the data store. Authentication/framework failures can instead use LegacyErrorEnvelope. Quotas are 402; conflicts 409; unsupported operators and sorts needing an index 501."
            },
            "DataTableGroup": {
                "type": "object",
                "description": "A named folder of related tables inside the tenant's workspace, with a report layer that reads across every table in it.",
                "required": [
                    "id",
                    "name",
                    "slug",
                    "position",
                    "tables_count",
                    "records_count"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The group id; the `{group}` path parameter everywhere else."
                    },
                    "name": {
                        "type": "string",
                        "description": "Display name."
                    },
                    "slug": {
                        "type": "string",
                        "description": "URL-safe name, unique within the tenant."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the group holds."
                    },
                    "icon": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "An emoji shown before the name, or null."
                    },
                    "color": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One of the select-option palette keys (gray, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose), or null."
                    },
                    "position": {
                        "type": "integer",
                        "description": "Order among the tenant's groups, first = 0."
                    },
                    "tables_count": {
                        "type": "integer",
                        "description": "Member tables."
                    },
                    "records_count": {
                        "type": "integer",
                        "description": "Live records across the member tables."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was created (ISO-8601)."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it last changed (ISO-8601)."
                    }
                }
            },
            "DataDrill": {
                "type": "object",
                "description": "How to open the table's Records view on exactly the rows behind a number: `GET /api/v3/data/tables/{table_id}/records?filter=<filter>`.",
                "required": [
                    "table_id",
                    "filter",
                    "range"
                ],
                "properties": {
                    "table_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The table id."
                    },
                    "filter": {
                        "$ref": "#/components/schemas/DataCondition",
                        "description": "A condition tree for the records endpoint."
                    },
                    "range": {
                        "type": "object",
                        "required": [
                            "from",
                            "to"
                        ],
                        "properties": {
                            "from": {
                                "type": "string",
                                "format": "date-time",
                                "description": "Start of the window (inclusive, ISO-8601)."
                            },
                            "to": {
                                "type": "string",
                                "format": "date-time",
                                "description": "End of the window (exclusive, ISO-8601)."
                            }
                        },
                        "description": "The half-open [from, to) window."
                    }
                }
            },
            "DataGroupTableCard": {
                "type": "object",
                "description": "One member table as the group overview shows it.",
                "required": [
                    "id",
                    "name",
                    "slug",
                    "records_count",
                    "columns_count",
                    "headline",
                    "created_last_range",
                    "drill"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The id."
                    },
                    "name": {
                        "type": "string",
                        "description": "Display name."
                    },
                    "slug": {
                        "type": "string",
                        "description": "URL-safe name, unique within the tenant."
                    },
                    "icon": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "An emoji shown before the name, or null."
                    },
                    "records_count": {
                        "type": "integer",
                        "description": "Live records in the table."
                    },
                    "columns_count": {
                        "type": "integer",
                        "description": "Columns defined on the table."
                    },
                    "headline": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The first amount-like column's total over the range, or null when the table has none.",
                        "properties": {
                            "label": {
                                "type": "string",
                                "description": "Human label."
                            },
                            "fn": {
                                "type": "string",
                                "enum": [
                                    "sum"
                                ],
                                "description": "The aggregate."
                            },
                            "column": {
                                "type": "string",
                                "description": "The column key."
                            },
                            "value": {
                                "type": [
                                    "number",
                                    "null"
                                ],
                                "description": "The computed value, or null when nothing matched."
                            },
                            "unit": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The column's unit (e.g. TZS), or null."
                            }
                        }
                    },
                    "created_last_range": {
                        "type": "integer",
                        "description": "Records created inside the range."
                    },
                    "drill": {
                        "$ref": "#/components/schemas/DataDrill",
                        "description": "How to open the rows behind the number."
                    },
                    "columns": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataColumn"
                        },
                        "description": "The table's columns in the schema shape (`GET /groups/{group}` only)."
                    }
                }
            },
            "DataGroupOverview": {
                "type": "object",
                "description": "The group's overview for a range, derived at read time (cached 60 s, invalidated by any write to a member table).",
                "required": [
                    "totals",
                    "tables",
                    "over_time",
                    "headlines",
                    "relations",
                    "range"
                ],
                "properties": {
                    "totals": {
                        "type": "object",
                        "required": [
                            "tables",
                            "records",
                            "storage_bytes"
                        ],
                        "properties": {
                            "tables": {
                                "type": "integer",
                                "description": "Member tables."
                            },
                            "records": {
                                "type": "integer",
                                "description": "Live records across the group."
                            },
                            "storage_bytes": {
                                "type": "integer",
                                "description": "JSONB bytes across the group."
                            }
                        },
                        "description": "Sums across the member tables."
                    },
                    "tables": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/DataGroupTableCard"
                        },
                        "description": "Member tables."
                    },
                    "over_time": {
                        "type": "object",
                        "description": "Records created per bucket, stacked by table. The bucket follows the range: day up to 31 days, week up to 182, else month.",
                        "required": [
                            "bucket",
                            "rows"
                        ],
                        "properties": {
                            "bucket": {
                                "type": "string",
                                "enum": [
                                    "day",
                                    "week",
                                    "month"
                                ],
                                "description": "The bucket start date."
                            },
                            "rows": {
                                "type": "array",
                                "items": {
                                    "type": "object",
                                    "required": [
                                        "bucket",
                                        "total",
                                        "by_table"
                                    ],
                                    "properties": {
                                        "bucket": {
                                            "type": "string",
                                            "format": "date",
                                            "description": "The bucket start date."
                                        },
                                        "total": {
                                            "type": "integer",
                                            "description": "Records across every table in the bucket."
                                        },
                                        "by_table": {
                                            "type": "object",
                                            "additionalProperties": {
                                                "type": "integer"
                                            },
                                            "description": "table id \u2192 records created in the bucket."
                                        },
                                        "drill": {
                                            "type": "object",
                                            "additionalProperties": {
                                                "$ref": "#/components/schemas/DataDrill"
                                            },
                                            "description": "table id \u2192 drill for that bucket."
                                        }
                                    }
                                },
                                "description": "One row per bucket, oldest first."
                            }
                        }
                    },
                    "headlines": {
                        "type": "array",
                        "description": "Every amount-like number column across the group (a key or label naming money, or `config.ui.is_summary_metric`), totalled over the range.",
                        "items": {
                            "type": "object",
                            "required": [
                                "table_id",
                                "table",
                                "label",
                                "fn",
                                "column",
                                "value",
                                "unit",
                                "chart",
                                "drill"
                            ],
                            "properties": {
                                "table_id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "description": "The table id."
                                },
                                "table": {
                                    "type": "string",
                                    "description": "The table's display name."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "Human label."
                                },
                                "fn": {
                                    "type": "string",
                                    "description": "The aggregate."
                                },
                                "column": {
                                    "type": "string",
                                    "description": "The column key."
                                },
                                "value": {
                                    "type": [
                                        "number",
                                        "null"
                                    ],
                                    "description": "The computed value, or null when nothing matched."
                                },
                                "unit": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The column's unit (e.g. TZS), or null."
                                },
                                "chart": {
                                    "type": "string",
                                    "enum": [
                                        "number"
                                    ],
                                    "description": "How the card is drawn."
                                },
                                "drill": {
                                    "$ref": "#/components/schemas/DataDrill",
                                    "description": "How to open the rows behind the number."
                                }
                            }
                        }
                    },
                    "relations": {
                        "type": "array",
                        "description": "Relation columns whose target table is inside the group.",
                        "items": {
                            "type": "object",
                            "required": [
                                "from_table_id",
                                "from_column",
                                "to_table_id"
                            ],
                            "properties": {
                                "from_table_id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "description": "The table holding the relation column."
                                },
                                "from_column": {
                                    "type": "string",
                                    "description": "The relation column key."
                                },
                                "to_table_id": {
                                    "type": "string",
                                    "format": "uuid",
                                    "description": "The table the relation points at."
                                }
                            }
                        }
                    },
                    "range": {
                        "type": "object",
                        "required": [
                            "from",
                            "to"
                        ],
                        "properties": {
                            "from": {
                                "type": "string",
                                "format": "date-time",
                                "description": "Start of the window (inclusive, ISO-8601)."
                            },
                            "to": {
                                "type": "string",
                                "format": "date-time",
                                "description": "End of the window (exclusive, ISO-8601)."
                            },
                            "relative": {
                                "type": "string",
                                "description": "The preset the range came from, when it did."
                            }
                        },
                        "description": "The half-open [from, to) window."
                    },
                    "computed_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the numbers were computed (ISO-8601)."
                    }
                }
            },
            "DataGroupReport": {
                "type": "object",
                "description": "A saved cross-table report. The definition is the group-report shape: `series` (one measure per member table, or a `formula` over the other series' slugified labels), a `dimension` of `{\"column\":\"$created_at\",\"bucket\":\"week\"}` (shared time axis), `{\"kind\":\"table\"}` (one row per series) or null (one number per series), a `date_range`, a `chart`, and optionally `compare`, `sort`, `limit`.",
                "required": [
                    "id",
                    "group_id",
                    "name",
                    "definition",
                    "is_pinned"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The id."
                    },
                    "group_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The group id."
                    },
                    "name": {
                        "type": "string",
                        "description": "Display name."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One line on what it shows, or null."
                    },
                    "definition": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The report definition."
                    },
                    "is_pinned": {
                        "type": "boolean",
                        "description": "Pinned to the top of the Reports tab."
                    },
                    "is_default": {
                        "type": "boolean",
                        "description": "Always false for a saved report."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was created (ISO-8601)."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it last changed (ISO-8601)."
                    }
                }
            },
            "DataErrorDetails": {
                "type": "object",
                "properties": {
                    "code": {
                        "type": "string",
                        "description": "Stable refusal category.",
                        "enum": [
                            "validation_error",
                            "conflict",
                            "not_found",
                            "rate_limited",
                            "quota_exceeded",
                            "temporary_failure",
                            "permission_denied",
                            "not_supported",
                            "provider_failure"
                        ]
                    },
                    "message": {
                        "type": "string",
                        "description": "Human-readable explanation."
                    },
                    "retryable": {
                        "type": "boolean",
                        "description": "Whether repeating unchanged could succeed; still apply operation idempotency rules."
                    },
                    "field": {
                        "type": "string",
                        "description": "Field key associated with this refusal."
                    },
                    "expected_type": {
                        "type": "string",
                        "description": "Expected field type when available."
                    },
                    "received": {
                        "type": "string",
                        "description": "JSON type/shape description, not the submitted sensitive value."
                    },
                    "retry_after_seconds": {
                        "type": "integer",
                        "description": "Suggested wait before retry.",
                        "minimum": 0
                    },
                    "details": {
                        "type": "object",
                        "description": "Additional field errors, quota details or reason information.",
                        "additionalProperties": true
                    }
                },
                "required": [
                    "code",
                    "message",
                    "retryable"
                ]
            },
            "DataTableStates": {
                "type": "object",
                "properties": {
                    "table": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "Table UUID.",
                                "format": "uuid"
                            },
                            "name": {
                                "type": "string",
                                "description": "Table name."
                            },
                            "slug": {
                                "type": "string",
                                "description": "Table slug."
                            }
                        },
                        "required": [
                            "id",
                            "name",
                            "slug"
                        ],
                        "description": "Identity of the table whose status fields are described."
                    },
                    "fields": {
                        "type": "array",
                        "description": "One entry per status field; empty when the table has none.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "key": {
                                    "type": "string",
                                    "description": "Column key."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "Field label."
                                },
                                "required": {
                                    "type": "boolean",
                                    "description": "Whether a value is required."
                                },
                                "strict": {
                                    "type": "boolean",
                                    "description": "Whether configured transition restrictions apply."
                                },
                                "initial": {
                                    "type": "array",
                                    "description": "Allowed initial state keys.",
                                    "items": {
                                        "type": "string"
                                    }
                                },
                                "states": {
                                    "type": "array",
                                    "description": "All configured states and moves.",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "key": {
                                                "type": "string",
                                                "description": "State key to write."
                                            },
                                            "label": {
                                                "type": "string",
                                                "description": "Display label."
                                            },
                                            "color": {
                                                "type": "string",
                                                "description": "Display color."
                                            },
                                            "initial": {
                                                "type": "boolean",
                                                "description": "May be an initial record state."
                                            },
                                            "final": {
                                                "type": "boolean",
                                                "description": "Final-state marker."
                                            },
                                            "next": {
                                                "type": "array",
                                                "description": "Available outgoing moves, annotated for the caller.",
                                                "items": {
                                                    "type": "object",
                                                    "properties": {
                                                        "key": {
                                                            "type": "string",
                                                            "description": "Destination state key."
                                                        },
                                                        "label": {
                                                            "type": "string",
                                                            "description": "Destination label."
                                                        },
                                                        "color": {
                                                            "type": "string",
                                                            "description": "Display color."
                                                        },
                                                        "final": {
                                                            "type": "boolean",
                                                            "description": "Whether destination is final."
                                                        },
                                                        "action": {
                                                            "type": "string",
                                                            "description": "Label for this move."
                                                        },
                                                        "requires": {
                                                            "type": [
                                                                "string",
                                                                "null"
                                                            ],
                                                            "description": "Additional permission required for this move."
                                                        },
                                                        "allowed": {
                                                            "type": "boolean",
                                                            "description": "Whether this caller may make this move."
                                                        }
                                                    },
                                                    "required": [
                                                        "key",
                                                        "label",
                                                        "color",
                                                        "final",
                                                        "action",
                                                        "requires",
                                                        "allowed"
                                                    ]
                                                }
                                            }
                                        },
                                        "required": [
                                            "key",
                                            "label",
                                            "color",
                                            "initial",
                                            "final",
                                            "next"
                                        ]
                                    }
                                }
                            },
                            "required": [
                                "key",
                                "label",
                                "required",
                                "strict",
                                "initial",
                                "states"
                            ]
                        }
                    }
                },
                "required": [
                    "table",
                    "fields"
                ]
            },
            "EngineTaskResult": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string",
                        "description": "Domain execution outcome; inspect even on HTTP 200."
                    },
                    "run_uuid": {
                        "type": "string",
                        "description": "Stable run UUID.",
                        "format": "uuid"
                    },
                    "output": {
                        "type": [
                            "object",
                            "array",
                            "null"
                        ],
                        "description": "Agent output shaped by its execution contract.",
                        "additionalProperties": true,
                        "items": []
                    },
                    "denial_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Machine-readable reason when denied."
                    },
                    "usage": {
                        "type": "object",
                        "description": "Execution usage including token/cost values when available.",
                        "additionalProperties": true
                    }
                },
                "required": [
                    "status",
                    "run_uuid",
                    "output",
                    "denial_reason",
                    "usage"
                ]
            },
            "EngineTaskAccepted": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string",
                        "description": "Current run status."
                    },
                    "run_uuid": {
                        "type": "string",
                        "description": "Run UUID.",
                        "format": "uuid"
                    },
                    "execution_state": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Execution progress state."
                    },
                    "delivery_state": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Delivery progress separate from computation."
                    },
                    "deadline_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Execution deadline.",
                        "format": "date-time"
                    },
                    "status_url": {
                        "type": "string",
                        "description": "Authenticated run polling URL.",
                        "format": "uri"
                    },
                    "denial_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Reason when admission was denied."
                    }
                },
                "required": [
                    "status",
                    "run_uuid",
                    "execution_state",
                    "delivery_state",
                    "deadline_at",
                    "status_url",
                    "denial_reason"
                ]
            },
            "EngineRunDetail": {
                "type": "object",
                "properties": {
                    "run": {
                        "type": "object",
                        "properties": {
                            "uuid": {
                                "type": "string",
                                "description": "Run UUID.",
                                "format": "uuid"
                            },
                            "trigger": {
                                "type": "string",
                                "description": "Trigger that created this run."
                            },
                            "status": {
                                "type": "string",
                                "description": "Execution outcome/status."
                            },
                            "execution_state": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Fine-grained execution state."
                            },
                            "delivery_state": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Delivery state."
                            },
                            "deadline_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Execution deadline.",
                                "format": "date-time"
                            },
                            "denial_reason": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Denial reason, when present."
                            },
                            "output": {
                                "type": [
                                    "object",
                                    "array",
                                    "null"
                                ],
                                "description": "Agent output.",
                                "additionalProperties": true,
                                "items": []
                            },
                            "provider": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Model provider."
                            },
                            "model_name": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Model identifier."
                            },
                            "prompt_tokens": {
                                "type": "integer",
                                "description": "Prompt tokens."
                            },
                            "completion_tokens": {
                                "type": "integer",
                                "description": "Completion tokens."
                            },
                            "cost_wallet": {
                                "type": "number",
                                "description": "Usage cost in cost_currency."
                            },
                            "cost_currency": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Cost currency."
                            },
                            "duration_ms": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Duration in milliseconds."
                            },
                            "created_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Run creation time.",
                                "format": "date-time"
                            }
                        },
                        "required": [
                            "uuid",
                            "trigger",
                            "status",
                            "execution_state",
                            "delivery_state",
                            "deadline_at",
                            "denial_reason",
                            "output",
                            "provider",
                            "model_name",
                            "prompt_tokens",
                            "completion_tokens",
                            "cost_wallet",
                            "cost_currency",
                            "duration_ms",
                            "created_at"
                        ],
                        "description": "Current run outcome, execution state and accumulated model usage."
                    },
                    "children": {
                        "type": "array",
                        "description": "Child executions belonging to this tenant.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "uuid": {
                                    "type": "string",
                                    "description": "Run UUID.",
                                    "format": "uuid"
                                },
                                "status": {
                                    "type": "string",
                                    "description": "Execution outcome/status."
                                },
                                "execution_state": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "Fine-grained execution state."
                                },
                                "deadline_at": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "Execution deadline.",
                                    "format": "date-time"
                                }
                            },
                            "required": [
                                "uuid",
                                "status",
                                "execution_state",
                                "deadline_at"
                            ]
                        }
                    },
                    "steps": {
                        "type": "array",
                        "description": "Trace steps, including linked result steps when available.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "position": {
                                    "type": "integer",
                                    "description": "Step order."
                                },
                                "kind": {
                                    "type": "string",
                                    "description": "Step type."
                                },
                                "tool_name": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "Tool invoked, when applicable."
                                },
                                "arguments": {
                                    "type": [
                                        "object",
                                        "array",
                                        "null"
                                    ],
                                    "description": "Tool arguments; can contain sensitive business data.",
                                    "additionalProperties": true,
                                    "items": []
                                },
                                "result_preview": {
                                    "type": [
                                        "string",
                                        "object",
                                        "array",
                                        "null"
                                    ],
                                    "description": "Recorded result preview.",
                                    "additionalProperties": true,
                                    "items": []
                                },
                                "status": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "Step status."
                                },
                                "duration_ms": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "Step duration."
                                }
                            },
                            "required": [
                                "position",
                                "kind",
                                "tool_name",
                                "arguments",
                                "result_preview",
                                "status",
                                "duration_ms"
                            ]
                        }
                    }
                },
                "required": [
                    "run",
                    "children",
                    "steps"
                ]
            },
            "EngineRequestError": {
                "type": "object",
                "properties": {
                    "message": {
                        "type": "string",
                        "description": "Framework validation error."
                    },
                    "errors": {
                        "type": "object",
                        "description": "Field errors, including idempotency_key for an invalid header.",
                        "additionalProperties": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            }
                        }
                    }
                },
                "required": [
                    "message"
                ]
            },
            "EngineAdmissionError": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string",
                        "description": "busy, denied or conflict depending on the refusal."
                    },
                    "message": {
                        "type": "string",
                        "description": "Optional explanation."
                    },
                    "reason": {
                        "type": "string",
                        "description": "Ingress refusal code, e.g. ingress_busy."
                    },
                    "run_uuid": {
                        "type": "string",
                        "description": "Accepted/denied run UUID when known.",
                        "format": "uuid"
                    },
                    "denial_reason": {
                        "type": "string",
                        "description": "Capacity refusal code."
                    },
                    "retryable": {
                        "type": "boolean",
                        "description": "Whether a safe retry can succeed."
                    },
                    "retry_after": {
                        "type": "integer",
                        "description": "Suggested delay in seconds."
                    },
                    "status_url": {
                        "type": "string",
                        "description": "Run lookup URL when known.",
                        "format": "uri"
                    }
                },
                "required": [
                    "status"
                ]
            },
            "BusinessWebhookEvent": {
                "type": "object",
                "description": "Automation subscription delivery envelope. Verify the timestamped X-Momo-Signature before parsing the raw JSON bytes.",
                "required": [
                    "id",
                    "event",
                    "occurred_at",
                    "tenant_id",
                    "subject",
                    "actor",
                    "data",
                    "subscription"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Stable business event UUID; retain to deduplicate each subscription delivery.",
                        "format": "uuid"
                    },
                    "event": {
                        "type": "string",
                        "description": "Known business event key. Use event_keys from the event read API to discover live publishers.",
                        "example": "record.created"
                    },
                    "occurred_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Time the business event occurred, distinct from the signature delivery timestamp.",
                        "format": "date-time"
                    },
                    "tenant_id": {
                        "type": "integer",
                        "description": "Account that owns this business event."
                    },
                    "subject": {
                        "type": "object",
                        "description": "Business resource the event concerns.",
                        "properties": {
                            "type": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Resource family, such as data_record."
                            },
                            "id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Resource identifier within that family."
                            }
                        },
                        "required": [
                            "type",
                            "id"
                        ]
                    },
                    "actor": {
                        "type": [
                            "object",
                            "array"
                        ],
                        "description": "Publisher-provided actor attribution; shape varies by event source.",
                        "additionalProperties": true,
                        "items": []
                    },
                    "data": {
                        "type": [
                            "object",
                            "array"
                        ],
                        "description": "Publisher-provided event payload; shape varies by event key.",
                        "additionalProperties": true,
                        "items": []
                    },
                    "subscription": {
                        "type": "object",
                        "description": "Subscription that caused this delivery.",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "Local event subscription ID."
                            },
                            "label": {
                                "type": "string",
                                "description": "Subscription label at delivery time."
                            }
                        },
                        "required": [
                            "id",
                            "label"
                        ]
                    }
                }
            },
            "CatalogueChannel": {
                "type": "object",
                "description": "A shop's presence on one platform. A shop with no channels is complete and sells nowhere yet; publishing is something you add.",
                "required": [
                    "platform",
                    "label",
                    "is_connected"
                ],
                "properties": {
                    "platform": {
                        "type": "string",
                        "enum": [
                            "whatsapp",
                            "storefront",
                            "facebook",
                            "instagram",
                            "tiktok"
                        ],
                        "description": "Which platform this presence is on."
                    },
                    "label": {
                        "type": "string",
                        "description": "What the merchant named this connection."
                    },
                    "external_catalogue_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's own id for the catalogue."
                    },
                    "external_account_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account it is bound to \u2014 a WABA id for WhatsApp."
                    },
                    "public_slug": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Storefront address, when this is a hosted storefront."
                    },
                    "is_connected": {
                        "type": "boolean",
                        "description": "Whether customers can currently see it."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When products were last pushed to this platform."
                    }
                }
            },
            "ProductListing": {
                "type": "object",
                "description": "One product as one platform sees it. The same product can be live on your storefront and blocked on WhatsApp, and each row says so in its own words.",
                "required": [
                    "platform",
                    "state"
                ],
                "properties": {
                    "platform": {
                        "type": "string",
                        "description": "Which platform this listing is on."
                    },
                    "state": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "syncing",
                            "synced",
                            "failed",
                            "blocked",
                            "drifted"
                        ],
                        "description": "`blocked` is not a failure: nothing was attempted because the product is missing something this platform requires. `failed` means the platform refused a push and it will be retried. `drifted` means the platform's copy no longer matches ours \u2014 someone edited it there \u2014 and the shop's `source_of_truth` decides which copy wins."
                    },
                    "external_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's own product id once it is live."
                    },
                    "problem": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why this platform will not show the product yet."
                    },
                    "review_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's review verdict, where it has one."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When this listing last reached the platform."
                    },
                    "drift": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "additionalProperties": {
                            "type": "object",
                            "properties": {
                                "ours": {
                                    "description": "The value we hold."
                                },
                                "theirs": {
                                    "description": "The value the platform holds."
                                }
                            }
                        },
                        "description": "Field by field, what differs, while the listing is `drifted`. Cleared once resolved."
                    },
                    "drift_detected_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the difference was last seen."
                    }
                }
            },
            "SyncProblem": {
                "type": "object",
                "description": "One thing that went wrong in a bulk write. `stage` is the part that matters: `ingest` means the row was not stored, anything else is the name of a platform that stored it but will not show it.",
                "required": [
                    "sku",
                    "stage",
                    "reason"
                ],
                "properties": {
                    "sku": {
                        "type": "string",
                        "description": "The product code, or the row number when the row had no code."
                    },
                    "stage": {
                        "type": "string",
                        "description": "`ingest`, or a platform name such as `whatsapp`."
                    },
                    "reason": {
                        "type": "string",
                        "description": "What is wrong, in words a merchant can act on."
                    }
                }
            },
            "CatalogueSync": {
                "type": "object",
                "description": "One bulk write and what became of every row in it. A sync is created by the batch endpoint and finishes in the background; poll it until `status` is `completed` or `failed`.",
                "required": [
                    "id",
                    "catalogue_id",
                    "status",
                    "received"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Sync id. Use it to read this report back."
                    },
                    "catalogue_id": {
                        "type": "integer",
                        "description": "The catalogue that was written to."
                    },
                    "source": {
                        "type": "string",
                        "enum": [
                            "api",
                            "feed",
                            "import",
                            "ui"
                        ],
                        "description": "Where the rows came from."
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "upsert",
                            "replace"
                        ],
                        "description": "`upsert` leaves products the payload did not mention alone; `replace` retires them."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "running",
                            "completed",
                            "failed"
                        ],
                        "description": "Where the run has got to."
                    },
                    "idempotency_key": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The key the caller sent, if any."
                    },
                    "received": {
                        "type": "integer",
                        "description": "How many rows arrived."
                    },
                    "created": {
                        "type": "integer",
                        "description": "New products."
                    },
                    "updated": {
                        "type": "integer",
                        "description": "Products that changed."
                    },
                    "unchanged": {
                        "type": "integer",
                        "description": "Products that were already identical \u2014 nothing was re-published for these."
                    },
                    "rejected": {
                        "type": "integer",
                        "description": "Rows that could not be stored. Each one is in `problems`."
                    },
                    "retired": {
                        "type": "integer",
                        "description": "Products taken off sale, in `replace` mode only."
                    },
                    "platforms": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "object",
                            "additionalProperties": {
                                "type": "integer"
                            }
                        },
                        "description": "Per platform, how many listings ended in each state \u2014 for example `{\"whatsapp\": {\"synced\": 1960, \"blocked\": 34}}`."
                    },
                    "problems": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/SyncProblem"
                        },
                        "description": "Up to 200 problems, ingest refusals first."
                    },
                    "problems_truncated": {
                        "type": "boolean",
                        "description": "True when there were more than 200 problems and the list was cut."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Set only when the run itself failed."
                    },
                    "started_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the run began."
                    },
                    "finished_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it finished."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was accepted."
                    }
                }
            },
            "StockLevel": {
                "type": "object",
                "description": "What we believe is on the shelf for one product. `available` is the number that decides whether a customer may buy: on hand, minus whatever pending orders are holding.",
                "required": [
                    "sku",
                    "available",
                    "tracked"
                ],
                "properties": {
                    "sku": {
                        "type": "string",
                        "description": "Your product code."
                    },
                    "inventory": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Units on hand. Null means this product is not counted at all, which is normal and not a fault."
                    },
                    "reserved": {
                        "type": "integer",
                        "description": "Units pending orders are holding."
                    },
                    "available": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "What a customer can still buy: `inventory` minus `reserved`."
                    },
                    "availability": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The word platforms show, derived from `available` unless you state one."
                    },
                    "tracked": {
                        "type": "boolean",
                        "description": "False when the product carries no count. Orders for it are never held back."
                    }
                }
            },
            "InventoryMovement": {
                "type": "object",
                "description": "One event that moved a stock count. The ledger is append-only: `inventory` and `reserved` on a product are roll-ups of these rows.",
                "required": [
                    "id",
                    "kind",
                    "quantity"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Movement id."
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "reserve",
                            "release",
                            "commit",
                            "adjust",
                            "sync"
                        ],
                        "description": "`reserve` a pending order holding units \u00b7 `release` that hold ending without a sale \u00b7 `commit` the sale happening \u00b7 `adjust` a person changing the count \u00b7 `sync` your own system stating the level."
                    },
                    "quantity": {
                        "type": "integer",
                        "description": "Signed. `reserve` and `release` move the held figure; the rest move the shelf count."
                    },
                    "on_hand_after": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Units on hand once this movement was applied."
                    },
                    "reserved_after": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Units held once this movement was applied."
                    },
                    "order_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The order that caused it, where there was one."
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why, for adjustments and releases."
                    },
                    "actor": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Who or what moved it \u2014 a person, `api`, `flow`, `ivr`."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it happened."
                    }
                }
            },
            "Webhook": {
                "type": "object",
                "description": "One receiver you registered. The signing secret is never included in a read \u2014 it is shown once on create and once on rotate.",
                "required": [
                    "id",
                    "url",
                    "events",
                    "is_active"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Webhook id."
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Where we POST. Must be a public https address; http is refused on create and when the URL changes (endpoints registered over http before 26 September 2026 keep working until their URL is edited)."
                    },
                    "events": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The events this receiver gets."
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Switched on by you."
                    },
                    "paused_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "Set when the platform paused it after too many failures in a row."
                    },
                    "paused_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it was paused."
                    },
                    "consecutive_failures": {
                        "type": "integer",
                        "description": "Failures since the last successful delivery."
                    },
                    "last_delivered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "The last time this receiver answered 2xx."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was registered."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it last changed."
                    },
                    "filters": {
                        "type": "object",
                        "description": "Narrow which events of a kind reach this receiver. Only `lead` is defined: lead.* events are sent only for leads in these stages, with at least one of these labels, from these channels. An empty or missing list means any.",
                        "properties": {
                            "lead": {
                                "type": "object",
                                "description": "Filters for lead.* events.",
                                "properties": {
                                    "stages": {
                                        "type": "array",
                                        "description": "Only leads in these stages.",
                                        "items": {
                                            "type": "string",
                                            "enum": [
                                                "new",
                                                "contacted",
                                                "qualified",
                                                "opportunity",
                                                "won",
                                                "lost",
                                                "unqualified"
                                            ]
                                        }
                                    },
                                    "labels": {
                                        "type": "array",
                                        "description": "Only leads carrying one of these labels (names).",
                                        "items": {
                                            "type": "string"
                                        }
                                    },
                                    "channels": {
                                        "type": "array",
                                        "description": "Only leads that first came from these channels.",
                                        "items": {
                                            "type": "string",
                                            "enum": [
                                                "call",
                                                "whatsapp",
                                                "sms",
                                                "messenger",
                                                "instagram",
                                                "tiktok",
                                                "email",
                                                "comment",
                                                "form",
                                                "web",
                                                "chat",
                                                "manual",
                                                "import",
                                                "api"
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "headers": {
                        "type": "array",
                        "description": "The names of the custom headers sent with every delivery. Their values are stored encrypted and never returned.",
                        "items": {
                            "type": "string"
                        }
                    }
                }
            },
            "WebhookDelivery": {
                "type": "object",
                "description": "One attempt-series to hand one event to one receiver. Created before the first POST, updated after every attempt.",
                "required": [
                    "id",
                    "delivery_uid",
                    "event",
                    "status",
                    "attempts"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Delivery id."
                    },
                    "delivery_uid": {
                        "type": "string",
                        "description": "The `X-Delivery-Id` the receiver saw."
                    },
                    "event": {
                        "type": "string",
                        "description": "Event name."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "delivered",
                            "failed",
                            "skipped"
                        ],
                        "description": "`pending` is waiting for its next attempt. `failed` used every retry, or was refused with a 4xx. `skipped` was recorded while the endpoint was paused and never sent."
                    },
                    "attempts": {
                        "type": "integer",
                        "description": "How many times it was sent."
                    },
                    "next_attempt_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the next retry is due, while pending."
                    },
                    "last_attempt_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was last sent."
                    },
                    "delivered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the receiver answered 2xx."
                    },
                    "response_code": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The last HTTP status the receiver answered."
                    },
                    "response_excerpt": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The first kilobyte of the last response body."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What went wrong, in words."
                    },
                    "replay_of_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Set when this delivery is a replay of an earlier one."
                    },
                    "payload": {
                        "type": "object",
                        "description": "The body that was (or will be) sent."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the event happened."
                    }
                }
            },
            "CatalogueFeed": {
                "type": "object",
                "description": "A product feed URL the shop pulls from on a schedule \u2014 Google Shopping or Meta product feed XML, or CSV/JSON. The connector for a store that cannot call this API but can publish a feed, which is every store platform.",
                "required": [
                    "id",
                    "catalogue_id",
                    "url",
                    "schedule",
                    "mode",
                    "is_active"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Feed id."
                    },
                    "catalogue_id": {
                        "type": "integer",
                        "description": "The shop it fills."
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "Where the feed lives. Must be a public http(s) address; redirects are not followed."
                    },
                    "schedule": {
                        "type": "string",
                        "enum": [
                            "hourly",
                            "daily",
                            "manual"
                        ],
                        "description": "How often it is pulled. `manual` only on request."
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "upsert",
                            "replace"
                        ],
                        "description": "`replace` (the default) treats the feed as the whole catalogue and retires anything missing from it; `upsert` leaves unmentioned products alone."
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "Switched off automatically after ten failed pulls in a row; switch it back on once fixed."
                    },
                    "mapping": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "additionalProperties": {
                            "type": "integer"
                        },
                        "description": "Field key \u2192 column position. Guessed from the headers on the first pull and kept; send your own to correct it."
                    },
                    "last_pulled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was last fetched."
                    },
                    "next_pull_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it is next due."
                    },
                    "last_sync_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The sync report from the last pull \u2014 read it at `GET /catalogues/{catalogue}/syncs/{sync}`."
                    },
                    "last_error": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the last pull failed, if it did."
                    },
                    "consecutive_failures": {
                        "type": "integer",
                        "description": "Failed pulls since the last good one."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it was registered."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it last changed."
                    }
                }
            },
            "Flow": {
                "type": "object",
                "description": "A message flow as the API reads it: the card, not the graph. Ask for the graph with include=definition on the single-flow read.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The flow id."
                    },
                    "name": {
                        "type": "string",
                        "description": "What the workspace calls it."
                    },
                    "description": {
                        "type": "string",
                        "nullable": true,
                        "description": "The author's one-line description, when written."
                    },
                    "status": {
                        "type": "string",
                        "description": "draft, active, paused or archived. Only active flows answer customers.",
                        "enum": [
                            "draft",
                            "active",
                            "paused",
                            "archived"
                        ]
                    },
                    "priority": {
                        "type": "integer",
                        "description": "Trigger order: lower runs first when two live flows claim the same words."
                    },
                    "channels": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "description": "A channel key."
                        },
                        "description": "The channels it runs on. WhatsApp today."
                    },
                    "version": {
                        "type": "integer",
                        "description": "The DRAFT's optimistic-lock counter, incremented on every save. Send it back as expected_version when publishing."
                    },
                    "has_unpublished_changes": {
                        "type": "boolean",
                        "description": "Whether the draft differs from what is live."
                    },
                    "published_version": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The number of the version customers get right now, or null when nothing is live."
                    },
                    "published_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When the live version went live."
                    },
                    "node_count": {
                        "type": "integer",
                        "description": "How many steps the draft has."
                    },
                    "triggers": {
                        "type": "array",
                        "description": "What starts it.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "type": {
                                    "type": "string",
                                    "description": "keyword, cold_start, no_session_fallback, choice_id, manual\u2026"
                                },
                                "value": {
                                    "type": "string",
                                    "nullable": true,
                                    "description": "The trigger's single value, when it has one."
                                },
                                "values": {
                                    "type": "array",
                                    "items": {
                                        "type": "string",
                                        "description": "One word."
                                    },
                                    "description": "The trigger's list of values, when it has several."
                                }
                            }
                        }
                    },
                    "keywords": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "description": "One keyword, lower-cased."
                        },
                        "description": "Every keyword the triggers claim, lower-cased."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the flow was created."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the draft last changed."
                    },
                    "definition": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "The draft graph (nodes, entryNodeId, defaults) with secrets redacted. Only with include=definition."
                    }
                }
            },
            "FlowSession": {
                "type": "object",
                "description": "One customer's run through a flow. Never carries variables; the single-session read does, for a key whose issuer may read them.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The session id."
                    },
                    "flow_id": {
                        "type": "integer",
                        "description": "The flow it runs."
                    },
                    "flow_name": {
                        "type": "string",
                        "description": "The flow's name at read time."
                    },
                    "flow_version": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The published version number the session is pinned to."
                    },
                    "conversation_id": {
                        "type": "integer",
                        "description": "The inbox conversation it lives in."
                    },
                    "contact_id": {
                        "type": "integer",
                        "nullable": true,
                        "description": "The contact record, when the conversation has one."
                    },
                    "contact_name": {
                        "type": "string",
                        "nullable": true,
                        "description": "The customer's name as the inbox knows it."
                    },
                    "contact_identifier": {
                        "type": "string",
                        "description": "The customer's phone (or handle) as stored on the conversation."
                    },
                    "trigger": {
                        "type": "string",
                        "description": "What started it: inbound, manual, api, schedule, automation\u2026"
                    },
                    "status": {
                        "type": "string",
                        "description": "running, waiting, completed, failed, expired, superseded_by_human or cancelled."
                    },
                    "outcome": {
                        "type": "string",
                        "description": "The eight-word reading of the status for people: in_progress, completed, abandoned, handed_over, failed, expired, cancelled, ended_by_operator."
                    },
                    "ended_reason": {
                        "type": "string",
                        "nullable": true,
                        "description": "The runtime's own word for why it ended, when it has."
                    },
                    "node_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "The step it is on, or ended on."
                    },
                    "awaiting": {
                        "type": "string",
                        "nullable": true,
                        "description": "What a waiting session waits for: text, choice, media, location, form, timer, payment\u2026"
                    },
                    "turns": {
                        "type": "integer",
                        "description": "How many customer turns it has taken."
                    },
                    "resume_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When a timer wakes it, if one will."
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When it lapses if the customer says nothing."
                    },
                    "started_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When it started."
                    },
                    "ended_at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When it ended, or null while live."
                    }
                }
            },
            "FlowSessionStep": {
                "type": "object",
                "description": "One row of a session's trace, redacted.",
                "properties": {
                    "seq": {
                        "type": "integer",
                        "description": "The step's sequence number within the session."
                    },
                    "node_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "The step of the flow."
                    },
                    "node_kind": {
                        "type": "string",
                        "nullable": true,
                        "description": "The step's kind (send_text, ask_text, collect_payment\u2026)."
                    },
                    "kind": {
                        "type": "string",
                        "description": "entered, emitted, awaited, resumed, branched, error, skipped or ended."
                    },
                    "payload": {
                        "type": "object",
                        "additionalProperties": true,
                        "nullable": true,
                        "description": "What the step recorded, with customer-typed values redacted."
                    },
                    "duration_ms": {
                        "type": "integer",
                        "nullable": true,
                        "description": "How long the step took."
                    },
                    "at": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true,
                        "description": "When it happened."
                    }
                }
            },
            "FlowIssue": {
                "type": "object",
                "description": "One finding from the validator or the go-live readiness check.",
                "properties": {
                    "level": {
                        "type": "string",
                        "description": "error (refuses a publish) or warning.",
                        "enum": [
                            "error",
                            "warning"
                        ]
                    },
                    "node_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "The step the finding is about, when it is about one."
                    },
                    "field": {
                        "type": "string",
                        "nullable": true,
                        "description": "The step field, when the finding anchors to one."
                    },
                    "code": {
                        "type": "string",
                        "nullable": true,
                        "description": "A stable code; readiness:* names an account setting rather than the graph."
                    },
                    "message": {
                        "type": "string",
                        "description": "The finding in plain words."
                    },
                    "fix_href": {
                        "type": "string",
                        "nullable": true,
                        "description": "The page in the app that fixes a readiness finding."
                    }
                }
            },
            "MetaTemplateComponent": {
                "type": "object",
                "description": "One component in WhatsApp's own template shape \u2014 exactly what the Business Management API takes on `POST /{waba}/message_templates`. `type` is HEADER, BODY, FOOTER, BUTTONS, CAROUSEL or LIMITED_TIME_OFFER; the other keys are Meta's for that type (`format`, `text`, `example`, `buttons`, `cards`\u2026). See developers.facebook.com \u203a WhatsApp \u203a Message Templates \u203a Components.",
                "required": [
                    "type"
                ],
                "additionalProperties": true,
                "properties": {
                    "type": {
                        "type": "string",
                        "description": "Component type.",
                        "enum": [
                            "HEADER",
                            "BODY",
                            "FOOTER",
                            "BUTTONS",
                            "CAROUSEL",
                            "LIMITED_TIME_OFFER"
                        ]
                    },
                    "format": {
                        "type": "string",
                        "description": "HEADER only: `TEXT`, `IMAGE`, `VIDEO`, `DOCUMENT` or `LOCATION`."
                    },
                    "text": {
                        "type": "string",
                        "description": "HEADER (TEXT), BODY and FOOTER: the copy, with `{{1}}`-style or named placeholders."
                    },
                    "example": {
                        "type": "object",
                        "description": "Sample values for every placeholder, in the shape Meta wants: `{\"body_text\": [[\"Asha\", \"ORD-1042\"]]}`, `{\"header_text\": [\"Oda\"]}`, `{\"header_handle\": [\"<upload handle>\"]}`. Required by Meta whenever there is a placeholder or a media header.",
                        "additionalProperties": true
                    },
                    "buttons": {
                        "type": "array",
                        "description": "BUTTONS only: up to ten buttons \u2014 `QUICK_REPLY`, `URL`, `PHONE_NUMBER`, `COPY_CODE`, `FLOW`, `OTP`, `CATALOG`, `MPM`, `VOICE_CALL` \u2014 each in Meta's shape.",
                        "items": {
                            "type": "object",
                            "description": "One button.",
                            "additionalProperties": true
                        }
                    }
                }
            },
            "WhatsAppTemplateSubmission": {
                "type": "object",
                "description": "What happened when a template was submitted to Meta inside a request.",
                "properties": {
                    "submitted": {
                        "type": "boolean",
                        "description": "True when Meta accepted the submission in this request (read `whatsapp_status` and `whatsapp_template_id`)."
                    },
                    "queued": {
                        "type": "boolean",
                        "description": "True when Meta could not be reached and the submission was queued to retry; the template stays `pending` until it lands."
                    },
                    "message": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it was not submitted, when it was not \u2014 Meta's own words for a refusal, or that it is queued."
                    }
                }
            },
            "WhatsAppTemplateDeployment": {
                "type": "object",
                "description": "One template's presence on one WhatsApp Business Account other than the one it was created on. Each account reviews it separately.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Deployment id."
                    },
                    "whatsapp_business_account_id": {
                        "type": "string",
                        "description": "The WhatsApp Business Account this deployment is on."
                    },
                    "whatsapp_template_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's id for the template on THAT account (each account gets its own)."
                    },
                    "whatsapp_status": {
                        "type": "string",
                        "description": "Meta's review status on that account.",
                        "enum": [
                            "pending",
                            "in_review",
                            "approved",
                            "rejected",
                            "disabled",
                            "paused"
                        ]
                    },
                    "rejection_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's reason when rejected on that account."
                    },
                    "quality_rating": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Quality score on that account: `GREEN`, `YELLOW`, `RED`, `UNKNOWN` or null."
                    },
                    "category": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The category Meta assigned on that account, when it differs from the authored one."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When Meta last told us about it on that account.",
                        "format": "date-time"
                    }
                }
            },
            "WhatsAppTemplateSummary": {
                "type": "object",
                "description": "A WhatsApp template as the list returns it.",
                "required": [
                    "id",
                    "name",
                    "language",
                    "category",
                    "status",
                    "whatsapp_status"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Local template id \u2014 what every other template endpoint takes in its path."
                    },
                    "name": {
                        "type": "string",
                        "description": "The machine handle Meta knows it by: lowercase letters, digits and underscores, e.g. `order_shipped`. This is `template.name` on `POST /api/v3/whatsapp/send`.",
                        "pattern": "^[a-z0-9_]{1,512}$"
                    },
                    "display_name": {
                        "type": "string",
                        "description": "What a person on the dashboard calls it."
                    },
                    "language": {
                        "type": "string",
                        "description": "Language code of the copy, e.g. `sw`, `en`, `en_US`. One template per language."
                    },
                    "category": {
                        "type": "string",
                        "description": "Meta's category. `utility` for transactional notices, `marketing` for promotions, `authentication` for one-time codes. Meta may reclassify a template during review.",
                        "enum": [
                            "marketing",
                            "utility",
                            "authentication"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "Its state on this platform, before Meta gets a say. Only an `active` one can be sent; `archived` rows are hidden from the default list.",
                        "enum": [
                            "draft",
                            "active",
                            "archived"
                        ]
                    },
                    "whatsapp_status": {
                        "type": "string",
                        "description": "Where Meta's review got to. `pending` = not yet submitted (or a queued submission); `in_review` = Meta has it; `approved` = usable; `rejected` = see `rejection_reason`; `paused` / `disabled` = Meta stopped it for quality.",
                        "enum": [
                            "pending",
                            "in_review",
                            "approved",
                            "rejected",
                            "disabled",
                            "paused"
                        ]
                    },
                    "approved": {
                        "type": "boolean",
                        "description": "True when `whatsapp_status` is `approved`."
                    },
                    "sendable": {
                        "type": "boolean",
                        "description": "True when it can be sent right now: `status` active AND approved by Meta."
                    },
                    "rejection_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's reason, when `whatsapp_status` is `rejected` \u2014 a review verdict such as `INVALID_FORMAT`, or the refusal it gave the submission itself (a name clash, a body that starts with a variable). Null otherwise."
                    },
                    "whatsapp_business_account_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The WhatsApp Business Account (WABA) id it lives on. `GET /api/v3/whatsapp/accounts` lists them."
                    },
                    "whatsapp_template_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's own id for the template on that account. Null until a submission has been accepted."
                    },
                    "quality_rating": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's quality score on this account \u2014 `GREEN`, `YELLOW`, `RED` or `UNKNOWN` \u2014 once approved and in use. Null before that."
                    },
                    "parameter_format": {
                        "type": "string",
                        "description": "How variables are written: `POSITIONAL` (`{{1}}`, `{{2}}`) or `NAMED` (`{{order_id}}`).",
                        "enum": [
                            "POSITIONAL",
                            "NAMED"
                        ]
                    },
                    "variables": {
                        "type": "array",
                        "description": "The placeholders the header and body carry, in order \u2014 what a send must supply one value each for.",
                        "items": {
                            "type": "string",
                            "description": "A placeholder: `1`, `2`\u2026 or a name."
                        }
                    },
                    "body": {
                        "type": "string",
                        "description": "The body copy with its placeholders. The full component tree is on the single-template read."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When Meta last told us anything about this template (submission, poll, webhook or refresh).",
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was created here.",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row last changed here.",
                        "format": "date-time"
                    }
                }
            },
            "WhatsAppTemplate": {
                "type": "object",
                "description": "A WhatsApp template in full: the summary fields plus its content in both shapes and its deployments.",
                "required": [
                    "id",
                    "name",
                    "language",
                    "category",
                    "status",
                    "whatsapp_status",
                    "components",
                    "deployments"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Local template id \u2014 what every other template endpoint takes in its path."
                    },
                    "name": {
                        "type": "string",
                        "description": "The machine handle Meta knows it by: lowercase letters, digits and underscores, e.g. `order_shipped`. This is `template.name` on `POST /api/v3/whatsapp/send`.",
                        "pattern": "^[a-z0-9_]{1,512}$"
                    },
                    "display_name": {
                        "type": "string",
                        "description": "What a person on the dashboard calls it."
                    },
                    "language": {
                        "type": "string",
                        "description": "Language code of the copy, e.g. `sw`, `en`, `en_US`. One template per language."
                    },
                    "category": {
                        "type": "string",
                        "description": "Meta's category. `utility` for transactional notices, `marketing` for promotions, `authentication` for one-time codes. Meta may reclassify a template during review.",
                        "enum": [
                            "marketing",
                            "utility",
                            "authentication"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "description": "Its state on this platform, before Meta gets a say. Only an `active` one can be sent; `archived` rows are hidden from the default list.",
                        "enum": [
                            "draft",
                            "active",
                            "archived"
                        ]
                    },
                    "whatsapp_status": {
                        "type": "string",
                        "description": "Where Meta's review got to. `pending` = not yet submitted (or a queued submission); `in_review` = Meta has it; `approved` = usable; `rejected` = see `rejection_reason`; `paused` / `disabled` = Meta stopped it for quality.",
                        "enum": [
                            "pending",
                            "in_review",
                            "approved",
                            "rejected",
                            "disabled",
                            "paused"
                        ]
                    },
                    "approved": {
                        "type": "boolean",
                        "description": "True when `whatsapp_status` is `approved`."
                    },
                    "sendable": {
                        "type": "boolean",
                        "description": "True when it can be sent right now: `status` active AND approved by Meta."
                    },
                    "rejection_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's reason, when `whatsapp_status` is `rejected` \u2014 a review verdict such as `INVALID_FORMAT`, or the refusal it gave the submission itself (a name clash, a body that starts with a variable). Null otherwise."
                    },
                    "whatsapp_business_account_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The WhatsApp Business Account (WABA) id it lives on. `GET /api/v3/whatsapp/accounts` lists them."
                    },
                    "whatsapp_template_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's own id for the template on that account. Null until a submission has been accepted."
                    },
                    "quality_rating": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Meta's quality score on this account \u2014 `GREEN`, `YELLOW`, `RED` or `UNKNOWN` \u2014 once approved and in use. Null before that."
                    },
                    "parameter_format": {
                        "type": "string",
                        "description": "How variables are written: `POSITIONAL` (`{{1}}`, `{{2}}`) or `NAMED` (`{{order_id}}`).",
                        "enum": [
                            "POSITIONAL",
                            "NAMED"
                        ]
                    },
                    "variables": {
                        "type": "array",
                        "description": "The placeholders the header and body carry, in order \u2014 what a send must supply one value each for.",
                        "items": {
                            "type": "string",
                            "description": "A placeholder: `1`, `2`\u2026 or a name."
                        }
                    },
                    "body": {
                        "type": "string",
                        "description": "The body copy with its placeholders. The full component tree is on the single-template read."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When Meta last told us anything about this template (submission, poll, webhook or refresh).",
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row was created here.",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the row last changed here.",
                        "format": "date-time"
                    },
                    "header_type": {
                        "type": "string",
                        "description": "The header kind: `none`, `text`, `image`, `video` or `document`.",
                        "enum": [
                            "none",
                            "text",
                            "image",
                            "video",
                            "document"
                        ]
                    },
                    "header_text": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The header copy when `header_type` is `text`."
                    },
                    "footer": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The footer copy, up to 60 characters."
                    },
                    "buttons": {
                        "type": "array",
                        "description": "The flat-field buttons, when the template was described that way. `components` is the complete picture either way.",
                        "items": {
                            "type": "object",
                            "description": "One button: `type` (quick_reply, url, phone_number), `text`, and `url` or `phone_number`.",
                            "additionalProperties": true
                        }
                    },
                    "components": {
                        "type": "array",
                        "description": "The template in Meta's `components[]` shape \u2014 what is (or would be) submitted for review. Post it back unchanged to create a twin, or edit and PATCH it.",
                        "items": {
                            "$ref": "#/components/schemas/MetaTemplateComponent"
                        }
                    },
                    "deployments": {
                        "type": "array",
                        "description": "Its review status on every OTHER WhatsApp Business Account it has been deployed to (`POST \u2026/deployments`). Empty until deployed.",
                        "items": {
                            "$ref": "#/components/schemas/WhatsAppTemplateDeployment"
                        }
                    },
                    "submission": {
                        "$ref": "#/components/schemas/WhatsAppTemplateSubmission",
                        "description": "Only on responses that submitted to Meta (create, PATCH with content, submit): what happened."
                    },
                    "refresh": {
                        "type": "object",
                        "description": "Only on `POST \u2026/refresh`: `found_on_whatsapp` says whether Meta has the template, `message` explains when it does not.",
                        "properties": {
                            "found_on_whatsapp": {
                                "type": "boolean",
                                "description": "False when Meta has no template of this name and language on the account; the row is left as it was."
                            },
                            "message": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Explanation when not found."
                            }
                        }
                    }
                }
            },
            "WhatsAppTemplateWriteRequest": {
                "type": "object",
                "description": "What `POST /api/v3/whatsapp/templates` takes, and what `PATCH` accepts a subset of.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The machine handle: lowercase letters, digits and underscores, at most 512. Meta refuses anything else, so this API does too rather than silently changing it. Cannot change once created.",
                        "pattern": "^[a-z0-9_]{1,512}$",
                        "maxLength": 512
                    },
                    "language": {
                        "type": "string",
                        "description": "Language code, e.g. `sw`, `en`, `en_US`. Cannot change once created \u2014 another language is another template.",
                        "maxLength": 16
                    },
                    "category": {
                        "type": "string",
                        "description": "Meta category.",
                        "enum": [
                            "marketing",
                            "utility",
                            "authentication"
                        ]
                    },
                    "display_name": {
                        "type": "string",
                        "description": "A human name for the dashboard. Defaults to the name, title-cased.",
                        "maxLength": 255
                    },
                    "waba_id": {
                        "type": "string",
                        "description": "Which WhatsApp Business Account to create it on. Required only when the workspace has more than one; `GET /api/v3/whatsapp/accounts` lists them (`waba_id`). Cannot change once created \u2014 use deployments.",
                        "maxLength": 64
                    },
                    "status": {
                        "type": "string",
                        "description": "Local state. Defaults to `active`. `archived` hides it; `draft` keeps it out of the send picker.",
                        "enum": [
                            "draft",
                            "active",
                            "archived"
                        ]
                    },
                    "parameter_format": {
                        "type": "string",
                        "description": "How placeholders are written in the copy. Defaults to `POSITIONAL`.",
                        "enum": [
                            "POSITIONAL",
                            "NAMED"
                        ]
                    },
                    "submit": {
                        "type": "boolean",
                        "description": "Whether to submit to Meta in this request. Defaults to true. On PATCH, only a content change submits.",
                        "default": true
                    },
                    "components": {
                        "type": "array",
                        "description": "The content in WhatsApp's own `components[]` shape \u2014 one entry per HEADER, BODY, FOOTER, BUTTONS, CAROUSEL or LIMITED_TIME_OFFER, with Meta's `example` values. Covers everything Meta supports. Wins over the flat fields when both are sent; on PATCH, replaces the whole content.",
                        "items": {
                            "$ref": "#/components/schemas/MetaTemplateComponent"
                        },
                        "minItems": 1,
                        "maxItems": 12
                    },
                    "body": {
                        "type": "string",
                        "description": "Flat description: the body copy, up to 1,024 characters, with `{{1}}`-style placeholders. Required unless `components` is given. On PATCH, sending `body` re-describes the whole content with the flat fields.",
                        "maxLength": 1024
                    },
                    "header_type": {
                        "type": "string",
                        "description": "Flat description: header kind \u2014 `none` or `text` (with `header_text`). A media header (image, video, document) needs the sample handle Meta issues on upload, which only `components` can carry (`{\"type\":\"HEADER\",\"format\":\"IMAGE\",\"example\":{\"header_handle\":[\"\u2026\"]}}`).",
                        "enum": [
                            "none",
                            "text"
                        ]
                    },
                    "header_text": {
                        "type": "string",
                        "description": "Flat description: a one-line text header, up to 60 characters, one placeholder at most. Implies `header_type: text`.",
                        "maxLength": 60
                    },
                    "footer": {
                        "type": "string",
                        "description": "Flat description: footer copy, up to 60 characters, no placeholders.",
                        "maxLength": 60
                    },
                    "buttons": {
                        "type": "array",
                        "description": "Flat description: up to ten buttons of type `quick_reply`, `url` (with `url`; a `{{1}}` at its end makes it dynamic and then `example` is required) or `phone_number` (with `phone_number`). For copy-code, flow or catalogue buttons use `components`.",
                        "items": {
                            "type": "object",
                            "description": "One button.",
                            "properties": {
                                "type": {
                                    "type": "string",
                                    "description": "Button type.",
                                    "enum": [
                                        "quick_reply",
                                        "url",
                                        "phone_number"
                                    ]
                                },
                                "text": {
                                    "type": "string",
                                    "description": "Button label, up to 25 characters.",
                                    "maxLength": 25
                                },
                                "url": {
                                    "type": "string",
                                    "description": "For `url`: the link, optionally ending in `{{1}}`."
                                },
                                "phone_number": {
                                    "type": "string",
                                    "description": "For `phone_number`: the number to dial, in E.164."
                                },
                                "example": {
                                    "type": "string",
                                    "description": "For a dynamic `url`: a sample value for its `{{1}}`."
                                }
                            }
                        },
                        "maxItems": 10
                    },
                    "variable_samples": {
                        "type": "object",
                        "description": "Flat description: a sample value per placeholder, keyed by the placeholder (`\"1\"`, `\"2\"` or a name). Meta requires a sample for every placeholder; missing ones get a generic sample, which Meta may reject for marketing copy.",
                        "additionalProperties": {
                            "type": "string",
                            "description": "The sample value."
                        }
                    }
                }
            },
            "WhatsAppAccount": {
                "type": "object",
                "description": "A WhatsApp Business Account (WABA) connected to this workspace, with its numbers. `phone_numbers[].id` is what `sender_id` (sends, groups) and `from` (catalogue sends, flow sessions) take; `waba_id` is what the templates endpoints take.",
                "required": [
                    "waba_id",
                    "is_active",
                    "phone_numbers"
                ],
                "properties": {
                    "waba_id": {
                        "type": "string",
                        "description": "The WhatsApp Business Account id \u2014 `waba_id` on the templates endpoints."
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The business name Meta shows for the account."
                    },
                    "is_active": {
                        "type": "boolean",
                        "description": "False once the account has been disconnected; kept so its templates and catalogues still resolve."
                    },
                    "is_default": {
                        "type": "boolean",
                        "description": "True for the account a send without `sender_id` goes out from."
                    },
                    "phone_numbers": {
                        "type": "array",
                        "description": "The business phone numbers on the account.",
                        "items": {
                            "type": "object",
                            "description": "One number.",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "description": "Meta's phone_number_id \u2014 what `sender_id` and `from` take. The number itself (`phone_number` or `display`) is accepted there too."
                                },
                                "phone_number": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The number in E.164, when the connection recorded it."
                                },
                                "display": {
                                    "type": "string",
                                    "description": "The number as displayed."
                                },
                                "is_default": {
                                    "type": "boolean",
                                    "description": "True for the number a send without `sender_id` goes out from."
                                }
                            }
                        }
                    },
                    "quality_rating": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account's quality rating from Meta, when known."
                    },
                    "messaging_tier": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The account's messaging limit tier from Meta, when known."
                    },
                    "templates_count": {
                        "type": "integer",
                        "description": "How many templates live on this account here."
                    },
                    "catalogues_count": {
                        "type": "integer",
                        "description": "How many catalogues are connected to this account."
                    },
                    "last_synced_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the account details were last refreshed from the connection.",
                        "format": "date-time"
                    }
                }
            },
            "SmsSender": {
                "type": "object",
                "description": "One identity an SMS may go out as. `value` is exactly what `sender_id` takes on `/sms/send` and `/sms/campaign`.",
                "required": [
                    "type",
                    "value",
                    "label",
                    "status"
                ],
                "properties": {
                    "type": {
                        "type": "string",
                        "description": "What kind of identity: an approved alphanumeric sender ID, one of the workspace's own SMS-capable numbers, or an active short code.",
                        "enum": [
                            "sender_id",
                            "phone_number",
                            "short_code"
                        ]
                    },
                    "value": {
                        "type": "string",
                        "description": "Pass this as `sender_id`."
                    },
                    "label": {
                        "type": "string",
                        "description": "A human name for it: the sender ID itself, the number's label, or the short code's description."
                    },
                    "status": {
                        "type": "string",
                        "description": "`approved` for a sender ID, `active` for a number or short code \u2014 only usable identities are listed.",
                        "enum": [
                            "approved",
                            "active"
                        ]
                    }
                }
            },
            "ContactGroupField": {
                "type": "object",
                "description": "One extra field a group declares. Declaring it is what makes the dashboard show a column for it; a contact may still be given an undeclared key.",
                "required": [
                    "key"
                ],
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The key a contact carries it under, and what a campaign addresses as `{{cf:key}}`. Letters, digits, `_`, `.` and `-`.",
                        "maxLength": 64,
                        "pattern": "^[A-Za-z0-9_.-]+$"
                    },
                    "label": {
                        "type": "string",
                        "description": "What a person reading the dashboard sees. Defaults to the key.",
                        "maxLength": 120
                    },
                    "type": {
                        "type": "string",
                        "description": "How the dashboard renders and validates it. Defaults to `text`.",
                        "enum": [
                            "text",
                            "number",
                            "email",
                            "date",
                            "select"
                        ]
                    }
                }
            },
            "ContactGroup": {
                "type": "object",
                "description": "A contact group: the list every contact belongs to, and the small schema of extra fields its contacts may carry. Its `id` or `uid` is the `{group_id}` every contact path takes.",
                "required": [
                    "id",
                    "uid",
                    "name",
                    "status",
                    "contacts_count",
                    "subscribed_count",
                    "custom_fields"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Numeric id. Accepted anywhere a group is named."
                    },
                    "uid": {
                        "type": "string",
                        "description": "Stable UUID. Accepted anywhere the numeric id is, and the one to store.",
                        "format": "uuid"
                    },
                    "name": {
                        "type": "string",
                        "description": "What the group is called."
                    },
                    "status": {
                        "type": "string",
                        "description": "`active`, or `inactive` for a group kept for its history but no longer in use.",
                        "enum": [
                            "active",
                            "inactive"
                        ]
                    },
                    "contacts_count": {
                        "type": "integer",
                        "description": "How many people are in it, subscribed or not."
                    },
                    "subscribed_count": {
                        "type": "integer",
                        "description": "How many of those still accept messages \u2014 the number a campaign would actually reach."
                    },
                    "custom_fields": {
                        "type": "array",
                        "description": "The extra fields this group declares.",
                        "items": {
                            "$ref": "#/components/schemas/ContactGroupField"
                        }
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the group was created.",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed.",
                        "format": "date-time"
                    }
                }
            },
            "ContactGroupWriteRequest": {
                "type": "object",
                "description": "What `POST /api/v3/contact-groups` takes, and what `PATCH` accepts a subset of.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "What to call the group.",
                        "maxLength": 160
                    },
                    "status": {
                        "type": "string",
                        "description": "Defaults to `active` on create.",
                        "enum": [
                            "active",
                            "inactive"
                        ]
                    },
                    "custom_fields": {
                        "type": "array",
                        "description": "The extra fields contacts in this group may carry. On PATCH this REPLACES the declaration \u2014 a schema is not a thing to merge \u2014 and removing a field does not touch values already stored on contacts, they are simply no longer declared.",
                        "items": {
                            "$ref": "#/components/schemas/ContactGroupField"
                        },
                        "maxItems": 50
                    }
                }
            },
            "ContactBatchResult": {
                "type": "object",
                "description": "What one row of a bulk import did.",
                "properties": {
                    "index": {
                        "type": "integer",
                        "description": "The row's position in the `contacts` array you sent."
                    },
                    "uid": {
                        "type": "string",
                        "description": "The contact it created or matched."
                    },
                    "outcome": {
                        "type": "string",
                        "description": "`created`, `updated`, or `skipped` when `skip_existing` was set and the number was already there.",
                        "enum": [
                            "created",
                            "updated",
                            "skipped"
                        ]
                    }
                }
            },
            "ContactWriteRequest": {
                "type": "object",
                "description": "A contact. Every field that is not one of the reserved names below is stored as a custom field, at the TOP level of the object \u2014 do not wrap them in `custom_field_values`, which would store that wrapper as a key.",
                "additionalProperties": true,
                "properties": {
                    "PHONE": {
                        "type": "string",
                        "description": "The number. Required on create; on PATCH send it only when the number itself is changing. `phone_number` is an alias and `PHONE` wins if both are sent.",
                        "maxLength": 64
                    },
                    "country_code": {
                        "type": "string",
                        "description": "The country code to split off, e.g. `255`. Send it explicitly: a `+255\u2026` prefix alone is not inferred.",
                        "maxLength": 8
                    },
                    "name": {
                        "type": "string",
                        "description": "The person's name. `NAME`, or `FIRST_NAME` + `LAST_NAME`, are accepted instead. On create, a contact with no name given is named after their number; on PATCH, a name that is not sent is left alone.",
                        "maxLength": 160
                    },
                    "is_subscribed": {
                        "type": "boolean",
                        "description": "Whether they accept messages. Defaults true on create; left alone on PATCH when not sent."
                    }
                }
            },
            "PostTarget": {
                "type": "object",
                "description": "One account a post goes to, and how far it got there.",
                "required": [
                    "id",
                    "social_account_id",
                    "platform",
                    "status"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The target row id, for retry/delete-on-platform in the app."
                    },
                    "social_account_id": {
                        "type": "integer",
                        "description": "The connected social account."
                    },
                    "platform": {
                        "type": "string",
                        "description": "facebook, instagram, tiktok, youtube or linkedin."
                    },
                    "status": {
                        "type": "string",
                        "description": "pending, publishing, published, failed, needs_reconnect or cancelled.",
                        "enum": [
                            "pending",
                            "publishing",
                            "published",
                            "failed",
                            "needs_reconnect",
                            "cancelled"
                        ]
                    },
                    "provider_post_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The platform's own id for the post once published."
                    },
                    "permalink": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The public link once published."
                    },
                    "error_message": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why this target failed, in the platform's words."
                    },
                    "published_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it went up on this platform, ISO-8601."
                    }
                }
            },
            "PostMediaItem": {
                "type": "object",
                "description": "A media asset attached to a post.",
                "required": [
                    "asset"
                ],
                "properties": {
                    "asset": {
                        "type": "string",
                        "description": "The media asset uid, from POST /api/v3/posts/media."
                    },
                    "alt_text": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Alt text for the picture, where the platform supports it."
                    }
                }
            },
            "PostContent": {
                "type": "object",
                "description": "What is posted.",
                "required": [
                    "body",
                    "media"
                ],
                "properties": {
                    "body": {
                        "type": "string",
                        "description": "The text."
                    },
                    "media": {
                        "type": "array",
                        "description": "Attached media, in order.",
                        "items": {
                            "$ref": "#/components/schemas/PostMediaItem",
                            "description": "An attached media item."
                        }
                    },
                    "first_comment": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A comment posted under the post right after it goes up, where the platform allows it."
                    }
                }
            },
            "Post": {
                "type": "object",
                "description": "A publication: one piece of content going to one or more accounts.",
                "required": [
                    "uid",
                    "status",
                    "targets",
                    "content"
                ],
                "properties": {
                    "uid": {
                        "type": "string",
                        "description": "The post id (pub_\u2026)."
                    },
                    "status": {
                        "type": "string",
                        "description": "draft, scheduled, publishing, published, partially_published, failed or cancelled.",
                        "enum": [
                            "draft",
                            "scheduled",
                            "publishing",
                            "published",
                            "partially_published",
                            "failed",
                            "cancelled"
                        ]
                    },
                    "schedule_status": {
                        "type": "string",
                        "description": "The scheduler's own state: none, pending, claimed, dispatched, processed."
                    },
                    "scheduled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it goes (or went) out, ISO-8601."
                    },
                    "scheduled_tz": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The timezone the schedule was given in."
                    },
                    "published_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the first target went up."
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When every target settled."
                    },
                    "created_at": {
                        "type": "string",
                        "description": "When the post was created here, ISO-8601."
                    },
                    "updated_at": {
                        "type": "string",
                        "description": "Last change, ISO-8601."
                    },
                    "created_by": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Who created it: {id, name}."
                    },
                    "approved_by": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Who approved sending it: {id, name}."
                    },
                    "approved_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was approved for sending."
                    },
                    "content": {
                        "$ref": "#/components/schemas/PostContent",
                        "description": "What is posted: body, media, first comment."
                    },
                    "overrides": {
                        "type": "object",
                        "description": "Per-account content overrides, keyed by social account id."
                    },
                    "options": {
                        "type": "object",
                        "description": "Per-platform options, keyed by platform (YouTube title/privacy, TikTok privacy_level\u2026)."
                    },
                    "options_overrides": {
                        "type": "object",
                        "description": "Per-account option overrides, keyed by social account id."
                    },
                    "targets": {
                        "type": "array",
                        "description": "One row per account the post goes to.",
                        "items": {
                            "$ref": "#/components/schemas/PostTarget",
                            "description": "One target."
                        }
                    },
                    "media": {
                        "type": "array",
                        "description": "The attached assets as stored (uid, kind, url, status, probe).",
                        "items": {
                            "type": "object",
                            "description": "A stored media asset."
                        }
                    },
                    "verification": {
                        "type": "object",
                        "description": "The pre-flight: errors that block sending and warnings a person may accept by code."
                    },
                    "notes": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Internal notes."
                    },
                    "idempotency_key": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The key given on create, if any."
                    },
                    "approval": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "A pending approval hand-off (id, state, mode, at, requested_by, requested_at, expires_at, href), or null."
                    }
                }
            },
            "PostSummary": {
                "type": "object",
                "description": "A post as the list shows it.",
                "required": [
                    "uid",
                    "status",
                    "platforms"
                ],
                "properties": {
                    "uid": {
                        "type": "string",
                        "description": "The post id (pub_\u2026)."
                    },
                    "status": {
                        "type": "string",
                        "description": "draft, scheduled, publishing, published, partially_published, failed or cancelled."
                    },
                    "schedule_status": {
                        "type": "string",
                        "description": "The scheduler's own state."
                    },
                    "scheduled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it goes out, ISO-8601."
                    },
                    "scheduled_tz": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Timezone of the schedule."
                    },
                    "published_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it went out, ISO-8601."
                    },
                    "created_at": {
                        "type": "string",
                        "description": "When it was created, ISO-8601."
                    },
                    "body_excerpt": {
                        "type": "string",
                        "description": "The first 120 characters of the text."
                    },
                    "thumbnail": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Preview URL for the first media item (an image URL or video cover URL), or null."
                    },
                    "media_count": {
                        "type": "integer",
                        "description": "How many media items are attached."
                    },
                    "media_kind": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "image, video or mixed, or null for text only."
                    },
                    "platforms": {
                        "type": "array",
                        "description": "The platforms it goes to.",
                        "items": {
                            "type": "string",
                            "description": "A platform key."
                        }
                    },
                    "targets_summary": {
                        "type": "object",
                        "description": "Counts of targets by state."
                    },
                    "targets": {
                        "type": "array",
                        "description": "Per-target state, abbreviated.",
                        "items": {
                            "type": "object",
                            "description": "A target as the list shows it."
                        }
                    },
                    "comments_href": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A link into the comments desk for this post, once it has one."
                    },
                    "metrics": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Views, likes, comments, shares, reach from the nightly insights sync."
                    },
                    "comment_count": {
                        "type": "integer",
                        "description": "Comments received across targets."
                    },
                    "unanswered_count": {
                        "type": "integer",
                        "description": "Comments still needing an answer."
                    },
                    "created_by": {
                        "type": "object",
                        "description": "Who created it: {id, name}."
                    }
                }
            },
            "PostAccount": {
                "type": "object",
                "description": "A connected account a post can go to, with its publishing state.",
                "required": [
                    "id",
                    "platform",
                    "name",
                    "publish_enabled",
                    "publish_tier"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The social account id to pass as a target."
                    },
                    "platform": {
                        "type": "string",
                        "description": "facebook, instagram, tiktok, youtube or linkedin."
                    },
                    "name": {
                        "type": "string",
                        "description": "The account's name."
                    },
                    "handle": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Its @handle, when it has one."
                    },
                    "avatar": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Profile picture URL."
                    },
                    "publish_enabled": {
                        "type": "boolean",
                        "description": "Whether the account holds the publishing permission."
                    },
                    "needs_reconnect": {
                        "type": "boolean",
                        "description": "Whether the login has expired or been revoked."
                    },
                    "needs_reconnect_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why, when it does."
                    },
                    "reason_text": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "One sentence on why it cannot publish, when it cannot."
                    },
                    "publish_tier": {
                        "type": "string",
                        "description": "ready, needs_permission, waiting (platform review pending) or blocked."
                    },
                    "publish_state": {
                        "type": "string",
                        "description": "The raw grant state: on, available, missing, gated, off, not_applicable."
                    },
                    "publish_gate": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the workspace is waiting on, when gated."
                    },
                    "publish_defaults": {
                        "type": "object",
                        "description": "The options this account fills in by itself on a new post."
                    },
                    "insights_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the nightly metrics sync found: ok, scope_missing, unavailable, error."
                    },
                    "author_kind": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "LinkedIn only: person or organization."
                    },
                    "token_expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the login expires, if it does."
                    },
                    "health": {
                        "type": "object",
                        "description": "What the last health probe recorded."
                    }
                }
            },
            "PostMediaAsset": {
                "type": "object",
                "description": "A media file the business uploaded for posts.",
                "required": [
                    "uid",
                    "kind",
                    "status"
                ],
                "properties": {
                    "uid": {
                        "type": "string",
                        "description": "The asset uid to put in content.media."
                    },
                    "kind": {
                        "type": "string",
                        "description": "image or video."
                    },
                    "mime_type": {
                        "type": "string",
                        "description": "The served MIME type."
                    },
                    "original_name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The filename as uploaded."
                    },
                    "size": {
                        "type": "integer",
                        "description": "Bytes."
                    },
                    "status": {
                        "type": "string",
                        "description": "processing until probed and converted, then ready; failed when the file could not be used."
                    },
                    "url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the served copy lives."
                    },
                    "thumbnail_url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A poster frame for a video."
                    },
                    "probe": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "width, height, duration_ms, aspect, has_audio once known."
                    },
                    "warnings": {
                        "type": "array",
                        "description": "Anything the pipeline noticed (a resize, a re-encode).",
                        "items": {
                            "type": "string",
                            "description": "A warning code."
                        }
                    }
                }
            },
            "PostWriteRequest": {
                "type": "object",
                "description": "A post to create or replace.",
                "required": [
                    "targets",
                    "content"
                ],
                "properties": {
                    "targets": {
                        "type": "array",
                        "description": "Social account ids the post goes to (GET /api/v3/posts/accounts).",
                        "items": {
                            "type": "integer",
                            "description": "A social account id."
                        },
                        "minItems": 1,
                        "maxItems": 50
                    },
                    "content": {
                        "$ref": "#/components/schemas/PostContent",
                        "description": "What to post: body, media, first comment."
                    },
                    "overrides": {
                        "type": "object",
                        "description": "Per-account content overrides keyed by social account id: {body, media, first_comment}."
                    },
                    "options": {
                        "type": "object",
                        "description": "Per-platform options keyed by platform, validated against that platform's schema (YouTube: title, privacy, made_for_kids\u2026; TikTok: privacy_level\u2026). Omitted keys take the account's saved defaults."
                    },
                    "options_overrides": {
                        "type": "object",
                        "description": "Per-account option overrides keyed by social account id."
                    },
                    "schedule": {
                        "type": "object",
                        "description": "What to do once saved.",
                        "properties": {
                            "mode": {
                                "type": "string",
                                "description": "draft (default) saves only; now publishes at once; later schedules at `at`.",
                                "enum": [
                                    "draft",
                                    "now",
                                    "later"
                                ]
                            },
                            "at": {
                                "type": "string",
                                "description": "When to publish, ISO-8601, for later."
                            },
                            "tz": {
                                "type": "string",
                                "description": "IANA timezone for `at`."
                            }
                        }
                    },
                    "accept_warnings": {
                        "type": "array",
                        "description": "Pre-flight warning codes the caller accepts, for now/later.",
                        "items": {
                            "type": "string",
                            "description": "A warning code from verification."
                        }
                    },
                    "idempotency_key": {
                        "type": "string",
                        "description": "Any string of yours; the same key again returns the same post (200) instead of creating another."
                    },
                    "notes": {
                        "type": "string",
                        "description": "An internal note on the post."
                    }
                }
            },
            "PostPage": {
                "type": "object",
                "description": "A page of posts.",
                "required": [
                    "items",
                    "pagination"
                ],
                "properties": {
                    "items": {
                        "type": "array",
                        "description": "The posts, scheduled first then newest.",
                        "items": {
                            "$ref": "#/components/schemas/PostSummary",
                            "description": "A post as the list shows it."
                        }
                    },
                    "pagination": {
                        "$ref": "#/components/schemas/Pagination",
                        "description": "Page state."
                    }
                }
            },
            "OccasionLastCampaign": {
                "type": "object",
                "description": "The campaign this card last produced, compactly. `GET /api/v3/campaign/{uid}/view` has the rest.",
                "required": [
                    "uid",
                    "status",
                    "total_recipients",
                    "sent_count",
                    "failed_count",
                    "created_at"
                ],
                "properties": {
                    "uid": {
                        "type": "string",
                        "description": "The campaign uid (`cmp_*`)."
                    },
                    "status": {
                        "type": "string",
                        "description": "The campaign's status: `draft` while it queues, then `running`, `completed`, `paused` or `cancelled`."
                    },
                    "total_recipients": {
                        "type": "integer",
                        "description": "Recipients after the blacklist. Written when the round finishes queueing; 0 until then."
                    },
                    "sent_count": {
                        "type": "integer",
                        "description": "Messages handed to the operator so far."
                    },
                    "failed_count": {
                        "type": "integer",
                        "description": "Messages the operator refused so far."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the campaign was created (ISO 8601, UTC)."
                    }
                }
            },
            "Occasion": {
                "type": "object",
                "description": "One card: the catalogue's facts about the occasion and this workspace's decisions about it, with inheritance already applied.",
                "required": [
                    "key",
                    "name",
                    "name_sw",
                    "category",
                    "emoji",
                    "rule",
                    "is_public_holiday",
                    "confidence",
                    "caveat",
                    "enabled",
                    "customised",
                    "message",
                    "language",
                    "send_time",
                    "sender_id",
                    "contact_group_ids",
                    "audience",
                    "inherited",
                    "next_date",
                    "next_date_label",
                    "days_until",
                    "date_override",
                    "date_source",
                    "chars",
                    "segments",
                    "encoding",
                    "last_sent_on",
                    "last_campaign",
                    "updated_at"
                ],
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "Stable slug, the `{key}` every occasion route takes (`christmas-day`, `eid-al-fitr`, \u2026)."
                    },
                    "name": {
                        "type": "string",
                        "description": "English name."
                    },
                    "name_sw": {
                        "type": "string",
                        "description": "Kiswahili name."
                    },
                    "category": {
                        "type": "string",
                        "enum": [
                            "tanzania",
                            "religious",
                            "world"
                        ],
                        "description": "`tanzania` \u2014 national days; `religious` \u2014 Christian and Islamic; `world` \u2014 commercial and international days."
                    },
                    "emoji": {
                        "type": "string",
                        "description": "For a card in a UI only \u2014 never sent; one emoji turns a 160-character SMS into 70."
                    },
                    "rule": {
                        "type": "string",
                        "enum": [
                            "fixed",
                            "computed",
                            "table"
                        ],
                        "description": "How the date is known: the same day every year, derived from a rule (Easter, the fourth Thursday of November), or a table of moon-sighting estimates."
                    },
                    "is_public_holiday": {
                        "type": "boolean",
                        "description": "Whether Tanzania observes it as a public holiday."
                    },
                    "confidence": {
                        "type": "string",
                        "enum": [
                            "certain",
                            "approximate"
                        ],
                        "description": "`approximate` for the Islamic dates: set locally by moon sighting, so the catalogue's date can move by a day. Show `caveat`."
                    },
                    "caveat": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the date might move, when it might; null for a certain date."
                    },
                    "enabled": {
                        "type": "boolean",
                        "description": "Whether a greeting goes out on the day."
                    },
                    "customised": {
                        "type": "boolean",
                        "description": "True when the workspace wrote its own wording; false when `message` is the catalogue's."
                    },
                    "message": {
                        "type": "string",
                        "description": "What goes out, with `{{year}}` already filled. `{{name}}`, `{{store}}` and `{{shop_url}}` are filled per contact at send time."
                    },
                    "language": {
                        "type": "string",
                        "enum": [
                            "en",
                            "sw"
                        ],
                        "description": "Which catalogue wording is used when `message` is not custom."
                    },
                    "send_time": {
                        "type": "string",
                        "description": "`HH:MM` in Africa/Dar_es_Salaam \u2014 the customer's morning, not the server's."
                    },
                    "sender_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The approved sender ID the SMS goes out as; null when the workspace has none yet."
                    },
                    "contact_group_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "description": "A contact group id of this workspace."
                        },
                        "description": "Who receives it. Empty means every customer (every group)."
                    },
                    "audience": {
                        "type": "string",
                        "description": "`contact_group_ids` as a label: `All customers`, `Wateja wa Dar`, `Wateja wa Dar and 2 more`."
                    },
                    "inherited": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "message",
                                "language",
                                "send_time",
                                "sender_id",
                                "contact_group_ids"
                            ],
                            "description": "A field name."
                        },
                        "description": "The fields this card did not decide for itself: they read from the workspace defaults (`GET /api/v3/occasions/settings`) or the catalogue, and move when those move."
                    },
                    "next_date": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "The next day this greeting would go out on; null when the calendar cannot say (a table occasion past its known dates)."
                    },
                    "next_date_label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "`next_date` as `Fri, 25 Dec 2026`."
                    },
                    "days_until": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Whole days from today (Dar) to `next_date`; 0 means today."
                    },
                    "date_override": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "A date the workspace corrected the calendar to (the moon was sighted a day later). Wins over the catalogue for that occurrence."
                    },
                    "date_source": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "override",
                            "calendar",
                            null
                        ],
                        "description": "Where `next_date` came from; null when there is no `next_date`."
                    },
                    "chars": {
                        "type": "integer",
                        "description": "Characters in `message` with sample placeholders filled."
                    },
                    "segments": {
                        "type": "integer",
                        "description": "SMS segments that message costs, per recipient."
                    },
                    "encoding": {
                        "type": "string",
                        "enum": [
                            "GSM-7",
                            "UCS-2"
                        ],
                        "description": "`UCS-2` means a character outside GSM-7 (an emoji, a curly quote) cut the segment to 70 characters."
                    },
                    "last_sent_on": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "The last day it went out (scheduled or sent now)."
                    },
                    "last_campaign": {
                        "oneOf": [
                            {
                                "$ref": "#/components/schemas/OccasionLastCampaign"
                            },
                            {
                                "type": "null"
                            }
                        ],
                        "description": "The campaign this card last produced; null if it never has."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the card was last decided; null for a card nobody has touched."
                    }
                }
            },
            "OccasionSenderOption": {
                "type": "object",
                "description": "A sender ID the workspace has, with its approval status.",
                "required": [
                    "sender_id",
                    "status"
                ],
                "properties": {
                    "sender_id": {
                        "type": "string",
                        "description": "The sender ID text (the SMS `From`)."
                    },
                    "status": {
                        "type": "string",
                        "description": "`approved` may be chosen; the rest (`pending`, `rejected`) are listed so a UI can say \"awaiting approval\"."
                    }
                }
            },
            "OccasionContactGroupOption": {
                "type": "object",
                "description": "A contact group the audience may be set to.",
                "required": [
                    "id",
                    "name",
                    "contacts"
                ],
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The group id, what `contact_group_ids` takes."
                    },
                    "name": {
                        "type": "string",
                        "description": "The group's name."
                    },
                    "contacts": {
                        "type": "integer",
                        "description": "Members, before the blacklist."
                    }
                }
            },
            "OccasionSettings": {
                "type": "object",
                "description": "The workspace defaults every card inherits, with the choices they were made from.",
                "required": [
                    "sender_ids",
                    "sender_ids_available",
                    "contact_group_ids",
                    "contact_groups",
                    "send_time",
                    "language"
                ],
                "properties": {
                    "sender_ids": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "description": "An approved sender ID."
                        },
                        "description": "The approved sender IDs these greetings may use. The first is the default a card inherits. A workspace that never chose gets all its approved ones."
                    },
                    "sender_ids_available": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OccasionSenderOption"
                        },
                        "description": "Every sender ID the workspace has, with status."
                    },
                    "contact_group_ids": {
                        "type": "array",
                        "items": {
                            "type": "integer",
                            "description": "A contact group id."
                        },
                        "description": "Default audience. Empty means every customer."
                    },
                    "contact_groups": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/OccasionContactGroupOption"
                        },
                        "description": "Every contact group, to pick from."
                    },
                    "send_time": {
                        "type": "string",
                        "description": "`HH:MM`, Africa/Dar_es_Salaam."
                    },
                    "language": {
                        "type": "string",
                        "enum": [
                            "en",
                            "sw"
                        ],
                        "description": "Default catalogue wording language."
                    }
                }
            },
            "OccasionCatalogueEntry": {
                "type": "object",
                "description": "The catalogue half of a card, with no workspace state: what an integration keeps instead of its own calendar.",
                "required": [
                    "key",
                    "name",
                    "name_sw",
                    "category",
                    "emoji",
                    "rule",
                    "is_public_holiday",
                    "commercial",
                    "confidence",
                    "caveat",
                    "next_date",
                    "days_until",
                    "dates_known_until",
                    "sms_en",
                    "sms_sw",
                    "segments_en",
                    "segments_sw"
                ],
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "Stable slug, the `{key}` every occasion route takes."
                    },
                    "name": {
                        "type": "string",
                        "description": "English name."
                    },
                    "name_sw": {
                        "type": "string",
                        "description": "Kiswahili name."
                    },
                    "category": {
                        "type": "string",
                        "enum": [
                            "tanzania",
                            "religious",
                            "world"
                        ],
                        "description": "`tanzania`, `religious` or `world`."
                    },
                    "emoji": {
                        "type": "string",
                        "description": "For a UI only \u2014 never sent."
                    },
                    "rule": {
                        "type": "string",
                        "enum": [
                            "fixed",
                            "computed",
                            "table"
                        ],
                        "description": "How the date is known: fixed day, derived from a rule, or a table of moon-sighting estimates."
                    },
                    "is_public_holiday": {
                        "type": "boolean",
                        "description": "Whether Tanzania observes it as a public holiday."
                    },
                    "commercial": {
                        "type": "boolean",
                        "description": "Whether the standard wording invites a purchase (carries `{{shop_url}}`) or only greets."
                    },
                    "confidence": {
                        "type": "string",
                        "enum": [
                            "certain",
                            "approximate"
                        ],
                        "description": "`approximate` for moon-sighted dates."
                    },
                    "caveat": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the date might move; null for a certain date."
                    },
                    "next_date": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "The next occurrence on or after today (Dar); null past the catalogue's known dates."
                    },
                    "days_until": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Whole days until `next_date`; 0 means today."
                    },
                    "dates_known_until": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "For `table` occasions: the last date the catalogue knows. Past it the calendar answers null until the catalogue is extended. Null for the other rules."
                    },
                    "sms_en": {
                        "type": "string",
                        "description": "The standard English wording, `{{year}}` filled for `next_date`."
                    },
                    "sms_sw": {
                        "type": "string",
                        "description": "The standard Kiswahili wording."
                    },
                    "segments_en": {
                        "type": "integer",
                        "description": "Segments the English wording costs for this workspace (its name fills `{{store}}`)."
                    },
                    "segments_sw": {
                        "type": "integer",
                        "description": "Segments the Kiswahili wording costs for this workspace."
                    }
                }
            },
            "OccasionPreview": {
                "type": "object",
                "description": "What a message costs and how it reads. GSM-7 fits 160 characters in a segment; one character outside it (an emoji, a curly quote) forces UCS-2, where a segment is 70.",
                "required": [
                    "chars",
                    "segments",
                    "encoding",
                    "limit",
                    "rendered"
                ],
                "properties": {
                    "chars": {
                        "type": "integer",
                        "description": "Characters in the rendered message."
                    },
                    "segments": {
                        "type": "integer",
                        "description": "Segments per recipient \u2014 multiply by the audience for the cost in messages."
                    },
                    "encoding": {
                        "type": "string",
                        "enum": [
                            "GSM-7",
                            "UCS-2"
                        ],
                        "description": "The SMS encoding the text forces."
                    },
                    "limit": {
                        "type": "integer",
                        "description": "Characters per single segment in this encoding: 160 or 70."
                    },
                    "rendered": {
                        "type": "string",
                        "description": "The message with sample placeholders filled \u2014 `Amina`, the workspace name, its shop link \u2014 as a customer would read it."
                    }
                }
            },
            "OccasionRefusalEnvelope": {
                "type": "object",
                "description": "A refusal the business rules made (not a validation failure): the legacy error envelope plus a machine-readable `code` and, for money, the shortfall.",
                "required": [
                    "status",
                    "message",
                    "code"
                ],
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "error"
                        ],
                        "description": "Always \"error\"."
                    },
                    "message": {
                        "type": "string",
                        "description": "Human-readable reason."
                    },
                    "code": {
                        "type": "string",
                        "enum": [
                            "unknown_occasion",
                            "no_recipients",
                            "insufficient_balance",
                            "no_sender",
                            "sender_unavailable",
                            "no_user"
                        ],
                        "description": "What to branch on. `unknown_occasion` (404) \u2014 the key is not in the catalogue; `no_recipients` \u2014 the chosen groups have no contacts; `insufficient_balance` \u2014 `details` carries `required`, `balance`, `currency`; `no_sender` \u2014 the workspace has no approved sender ID; `sender_unavailable` \u2014 the card's sender ID is no longer approved."
                    },
                    "details": {
                        "type": "object",
                        "description": "Code-specific facts, present only when there are any. For `insufficient_balance`: `required` (number), `balance` (number), `currency` (string).",
                        "additionalProperties": true
                    }
                }
            },
            "WhatsAppFormQuestion": {
                "type": "object",
                "description": "One question. `key` is the saved-as name: the field in every answer, the flow variable and the Daftari column. It cannot change type after the first publish.",
                "required": [
                    "key",
                    "type",
                    "label"
                ],
                "properties": {
                    "key": {
                        "type": "string",
                        "pattern": "^[a-z][a-z0-9_]{0,39}$",
                        "description": "Saved-as name.",
                        "example": "jina_kamili"
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "short_text",
                            "long_text",
                            "number",
                            "email",
                            "phone",
                            "choice",
                            "choices",
                            "dropdown",
                            "date",
                            "optin",
                            "photo",
                            "document",
                            "info"
                        ],
                        "description": "What the question is. `GET /api/v3/whatsapp/forms/question-types` lists each with its WhatsApp component and limits."
                    },
                    "label": {
                        "type": "string",
                        "description": "The question. WhatsApp shows at most 20 characters for text, number, email, phone and dropdown questions (30 for choices, 40 for dates).",
                        "example": "Jina kamili"
                    },
                    "help": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "maxLength": 80,
                        "description": "Help text under the question."
                    },
                    "required": {
                        "type": "boolean",
                        "default": false,
                        "description": "Whether the customer must answer before continuing."
                    },
                    "sensitive": {
                        "type": "boolean",
                        "default": false,
                        "description": "Hidden from the summary WhatsApp shows the customer."
                    },
                    "options": {
                        "type": "array",
                        "description": "For choice, choices and dropdown: up to 20 (dropdown 200).",
                        "items": {
                            "type": "object",
                            "required": [
                                "key",
                                "label"
                            ],
                            "properties": {
                                "key": {
                                    "type": "string",
                                    "description": "The option's key \u2014 what the answer carries."
                                },
                                "label": {
                                    "type": "string",
                                    "maxLength": 30,
                                    "description": "What the customer reads."
                                },
                                "description": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "maxLength": 300,
                                    "description": "An optional second line under the label."
                                }
                            }
                        }
                    },
                    "min_length": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Fewest characters for a text answer."
                    },
                    "max_length": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Most characters for a text answer."
                    },
                    "min": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "Number questions: checked when the answer arrives."
                    },
                    "max": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "Largest number accepted (checked when the answer arrives)."
                    },
                    "min_selected": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Fewest choices for a several-choices question."
                    },
                    "max_selected": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Most choices for a several-choices question."
                    },
                    "min_date": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "Earliest date the picker allows (YYYY-MM-DD)."
                    },
                    "max_date": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date",
                        "description": "Latest date the picker allows (YYYY-MM-DD)."
                    },
                    "max_files": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 10,
                        "description": "Photo and document questions. A form holds one, on its last page."
                    },
                    "text": {
                        "type": "string",
                        "description": "Info blocks: the text shown."
                    }
                }
            },
            "WhatsAppFormDefinition": {
                "type": "object",
                "description": "The form: pages of questions. One WhatsApp screen per page; the last page sends.",
                "required": [
                    "pages"
                ],
                "properties": {
                    "pages": {
                        "type": "array",
                        "maxItems": 10,
                        "items": {
                            "type": "object",
                            "required": [
                                "title",
                                "questions"
                            ],
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "description": "Screen id (uppercase letters and underscores). Assigned when missing.",
                                    "example": "SCREEN_A"
                                },
                                "title": {
                                    "type": "string",
                                    "maxLength": 30,
                                    "example": "Taarifa zako",
                                    "description": "The page title WhatsApp shows at the top (30 characters)."
                                },
                                "intro": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "Text above the questions."
                                },
                                "questions": {
                                    "type": "array",
                                    "maxItems": 20,
                                    "items": {
                                        "$ref": "#/components/schemas/WhatsAppFormQuestion"
                                    },
                                    "description": "The questions on this page, in order."
                                }
                            }
                        },
                        "description": "The pages, in order. One page is one WhatsApp screen."
                    },
                    "continue_label": {
                        "type": "string",
                        "maxLength": 35,
                        "default": "Endelea",
                        "description": "The button that moves to the next page."
                    },
                    "submit_label": {
                        "type": "string",
                        "maxLength": 35,
                        "default": "Tuma",
                        "description": "The button on the last page that sends the answers."
                    }
                }
            },
            "WhatsAppFormSummary": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The form's id (uuid) \u2014 use it in every forms URL."
                    },
                    "name": {
                        "type": "string",
                        "description": "The form's name, as the Forms page shows it."
                    },
                    "purpose": {
                        "type": "string",
                        "description": "Meta category: SIGN_UP, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY, SIGN_IN or OTHER."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "draft",
                            "live",
                            "attention",
                            "retired"
                        ],
                        "description": "`attention`: WhatsApp throttled or blocked the live version, or the last change was refused."
                    },
                    "live_version": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The number of the version customers receive; null until the first publish."
                    },
                    "meta_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "WhatsApp's status of the live version."
                    },
                    "pages": {
                        "type": "integer",
                        "description": "The pages, in order. One page is one WhatsApp screen."
                    },
                    "questions": {
                        "type": "integer",
                        "description": "How many questions produce an answer."
                    },
                    "waba_id": {
                        "type": "string",
                        "description": "The WhatsApp business account the form lives in."
                    },
                    "data_table_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The Daftari table answers save to."
                    },
                    "origin": {
                        "type": "string",
                        "enum": [
                            "builder",
                            "table",
                            "imported",
                            "flow"
                        ],
                        "description": "How the form was made: builder, table, imported, flow or menu."
                    },
                    "read_only": {
                        "type": "boolean",
                        "description": "Imported from WhatsApp Manager with parts the builder cannot edit."
                    },
                    "answers": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Answers received so far."
                    },
                    "last_answer_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the latest answer arrived."
                    },
                    "used_in": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "properties": {
                            "flows": {
                                "type": "integer",
                                "description": "Message flows with a step that sends it."
                            },
                            "templates": {
                                "type": "integer",
                                "description": "Templates with an Open form button for it."
                            }
                        },
                        "description": "Where the form is used."
                    },
                    "updated_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "Last change to the form."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the form was made."
                    },
                    "accounts_count": {
                        "type": "integer",
                        "description": "How many WhatsApp accounts the form is on, its home included.",
                        "example": 2
                    }
                }
            },
            "WhatsAppForm": {
                "type": "object",
                "description": "One form with its working copy, settings, versions and numbers.",
                "properties": {
                    "form": {
                        "allOf": [
                            {
                                "$ref": "#/components/schemas/WhatsAppFormSummary"
                            },
                            {
                                "type": "object",
                                "properties": {
                                    "definition": {
                                        "$ref": "#/components/schemas/WhatsAppFormDefinition"
                                    },
                                    "settings": {
                                        "type": "object",
                                        "properties": {
                                            "message": {
                                                "type": "string",
                                                "description": "Text sent with the form."
                                            },
                                            "cta": {
                                                "type": "string",
                                                "maxLength": 20,
                                                "description": "The button that opens it."
                                            },
                                            "reply_text": {
                                                "type": "string",
                                                "description": "Sent after an answer that did not come from a flow or an AI agent."
                                            },
                                            "notify_on_answer": {
                                                "type": "boolean"
                                            },
                                            "send_lifetime_hours": {
                                                "type": "integer",
                                                "description": "How long a sent form stays answerable."
                                            },
                                            "template_id": {
                                                "type": [
                                                    "integer",
                                                    "null"
                                                ],
                                                "description": "An approved template with an Open form button, used outside the 24-hour window."
                                            },
                                            "phone_number_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            },
                                            "data_map": {
                                                "type": "object",
                                                "additionalProperties": {
                                                    "type": "string"
                                                },
                                                "description": "Question key \u2192 Daftari column key."
                                            }
                                        }
                                    }
                                }
                            }
                        ],
                        "description": "The form (WhatsAppFormSummary) with its definition and settings."
                    },
                    "versions": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "number": {
                                    "type": "integer",
                                    "description": "The version number."
                                },
                                "state": {
                                    "type": "string",
                                    "enum": [
                                        "draft",
                                        "published",
                                        "retired"
                                    ],
                                    "description": "draft, published or retired."
                                },
                                "meta_status": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "WhatsApp's status for it: DRAFT, PUBLISHED, THROTTLED, BLOCKED or DEPRECATED."
                                },
                                "is_live": {
                                    "type": "boolean",
                                    "description": "Whether new sends use this version."
                                },
                                "published_at": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "When it was published."
                                },
                                "retire_after": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "When an older version stops opening for customers who have it."
                                },
                                "open_sends": {
                                    "type": "integer",
                                    "description": "Sends of this version still waiting for an answer."
                                }
                            }
                        },
                        "description": "Every version, newest first."
                    },
                    "stats": {
                        "type": "object",
                        "properties": {
                            "sent_30d": {
                                "type": "integer",
                                "description": "Sends in the last 30 days."
                            },
                            "answered_30d": {
                                "type": "integer",
                                "description": "Of those, answered."
                            },
                            "answer_rate": {
                                "type": [
                                    "number",
                                    "null"
                                ],
                                "description": "answered \u00f7 sent, 0 to 1."
                            },
                            "median_seconds": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "Median time from send to answer."
                            },
                            "answers_total": {
                                "type": "integer",
                                "description": "Every answer ever received."
                            },
                            "not_saved": {
                                "type": "integer",
                                "description": "Answers the Daftari table refused (kept on the form)."
                            }
                        },
                        "description": "Numbers for the last 30 days."
                    },
                    "used_in": {
                        "type": "object",
                        "description": "Where the form is used."
                    },
                    "issues": {
                        "type": "array",
                        "description": "What would stop a publish, in plain words, with where it is.",
                        "items": {
                            "type": "object",
                            "properties": {
                                "path": {
                                    "type": "string",
                                    "description": "Where the problem is, e.g. pages.0.questions.2.label."
                                },
                                "page": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The page index."
                                },
                                "question": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The question key, when the problem is on one."
                                },
                                "code": {
                                    "type": "string",
                                    "description": "A stable code for the problem."
                                },
                                "message": {
                                    "type": "string",
                                    "description": "What to change, in one sentence."
                                }
                            }
                        }
                    },
                    "accounts": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/WhatsAppFormAccount"
                        },
                        "description": "Every WhatsApp account of the workspace: the form's home, the ones it was added to with the live version's state there, and the ones it could be added to."
                    }
                }
            },
            "WhatsAppFormAnswer": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The form's id (uuid) \u2014 use it in every forms URL."
                    },
                    "form_id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "The form's id (uuid)."
                    },
                    "form_name": {
                        "type": "string",
                        "description": "The form's name when the answer arrived."
                    },
                    "version": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The version that was answered."
                    },
                    "source": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "enum": [
                            "flow",
                            "template",
                            "api",
                            "mcp",
                            "ai",
                            "manual",
                            "test",
                            null
                        ],
                        "description": "What sent the form: flow, template, api, mcp, ai, manual or test."
                    },
                    "conversation_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The WhatsApp conversation the form goes to. Pass this or `to`."
                    },
                    "contact": {
                        "type": "object",
                        "properties": {
                            "name": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Their WhatsApp name."
                            },
                            "phone": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Their number, with country code."
                            }
                        },
                        "description": "Who answered."
                    },
                    "answers": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Keyed by question key: choices as keys, several choices as a list, numbers as numbers, dates as YYYY-MM-DD, agreements as booleans, uploads as file names. Null when the key's issuer may not export answers (then `lines` carries them with sensitive ones masked)."
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "key": {
                                    "type": "string",
                                    "description": "The question key."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "The question as asked."
                                },
                                "value": {
                                    "type": "string",
                                    "description": "The answer as text."
                                },
                                "redacted": {
                                    "type": "boolean",
                                    "description": "True when the question is sensitive and this key may not read it (value shows \u2022\u2022\u2022\u2022)."
                                }
                            }
                        },
                        "description": "The answers in words, in question order."
                    },
                    "files": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "question": {
                                    "type": "string",
                                    "description": "The question key."
                                },
                                "file_name": {
                                    "type": "string",
                                    "description": "The file's name."
                                },
                                "mime_type": {
                                    "type": "string",
                                    "description": "The file type."
                                },
                                "size": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "Size in bytes."
                                }
                            }
                        },
                        "description": "Photos and documents the customer uploaded."
                    },
                    "record": {
                        "type": "object",
                        "properties": {
                            "status": {
                                "type": "string",
                                "enum": [
                                    "saved",
                                    "failed",
                                    "skipped",
                                    "pending"
                                ],
                                "description": "pending, saved, failed or skipped."
                            },
                            "id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The row id."
                            },
                            "error": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Why the table refused the row, when it failed."
                            },
                            "table_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The table the row went to."
                            }
                        },
                        "description": "The Daftari row the answer became, when the form saves to a table."
                    },
                    "submitted_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the customer tapped Send."
                    }
                }
            },
            "Cart": {
                "type": "object",
                "description": "A basket, in the one shape every door produces (.plans/kikapu/02). A superset of the WhatsApp cart a flow's Ask for the cart stores.",
                "properties": {
                    "ref": {
                        "type": "string",
                        "description": "Its code (K7Q2M) once it has one, else its number."
                    },
                    "id": {
                        "type": "string",
                        "format": "uuid",
                        "description": "Its uuid."
                    },
                    "code": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The claim code that rides in a WhatsApp message."
                    },
                    "source": {
                        "type": "string",
                        "description": "storefront, chat_link, flow, agent, mcp, api, whatsapp_cart or whatsapp_menu."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "open",
                            "sent",
                            "claimed",
                            "ordered",
                            "abandoned",
                            "expired"
                        ],
                        "description": "open (being filled), sent (waiting in WhatsApp), ordered, abandoned (left), expired."
                    },
                    "items": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "description": "One basket line.",
                            "properties": {
                                "line_id": {
                                    "type": "integer",
                                    "description": "The line's id."
                                },
                                "product_id": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "The product."
                                },
                                "sku": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The product's SKU."
                                },
                                "retailer_id": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The retailer id WhatsApp's catalogue knows it by."
                                },
                                "name": {
                                    "type": "string",
                                    "description": "The product name."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "The line in words: name \u00b7 version (add-ons)."
                                },
                                "variant": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The version picked (Kamili), when the product has versions."
                                },
                                "variant_id": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ],
                                    "description": "Its id."
                                },
                                "options": {
                                    "type": "array",
                                    "description": "The add-ons picked.",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "group": {
                                                "type": "string",
                                                "description": "The add-on set."
                                            },
                                            "option": {
                                                "type": "string",
                                                "description": "The add-on."
                                            },
                                            "price_delta_minor": {
                                                "type": "integer",
                                                "description": "What it added, minor units."
                                            }
                                        }
                                    }
                                },
                                "addon_ids": {
                                    "type": "array",
                                    "items": {
                                        "type": "integer"
                                    },
                                    "description": "The add-ons' ids."
                                },
                                "note": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The customer's note for this line (no onions)."
                                },
                                "quantity": {
                                    "type": "integer",
                                    "description": "How many."
                                },
                                "unit_price_minor": {
                                    "type": "integer",
                                    "description": "One of them: the version's price plus the add-ons, minor units."
                                },
                                "line_total_minor": {
                                    "type": "integer",
                                    "description": "unit_price_minor \u00d7 quantity."
                                },
                                "currency": {
                                    "type": "string",
                                    "description": "ISO currency."
                                },
                                "image_url": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The product photo."
                                }
                            }
                        },
                        "description": "The lines."
                    },
                    "count": {
                        "type": "integer",
                        "description": "How many lines."
                    },
                    "quantity": {
                        "type": "integer",
                        "description": "How many things in all."
                    },
                    "subtotal_minor": {
                        "type": "integer",
                        "description": "The total, minor units."
                    },
                    "subtotal": {
                        "type": "string",
                        "description": "The total in words."
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO currency."
                    },
                    "note": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The order note."
                    },
                    "conversation_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The WhatsApp chat it belongs to."
                    },
                    "order_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The order it became."
                    },
                    "order_reference": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "#1042."
                    },
                    "shop": {
                        "type": "object",
                        "description": "The shop.",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "The shop id."
                            },
                            "name": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Its name."
                            },
                            "slug": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Its page address."
                            }
                        }
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When an unsent basket expires."
                    }
                }
            },
            "LeadCard": {
                "type": "object",
                "description": "A lead as a list row: enough to show it and decide whether to open it.",
                "required": [
                    "id",
                    "title",
                    "stage",
                    "closed",
                    "labels",
                    "currency",
                    "source_channel"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The lead's id (a uuid). Use it in every /leads/{lead} path.",
                        "format": "uuid"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The person's name, as given."
                    },
                    "title": {
                        "type": "string",
                        "description": "What to show as the lead's title: the name, else the company, phone or email."
                    },
                    "company": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Their business, if they gave one."
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Phone number in E.164 (+255\u2026)."
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Email address, lowercased."
                    },
                    "stage": {
                        "type": "string",
                        "description": "Where the lead is in the pipeline. won, lost and unqualified close it.",
                        "enum": [
                            "new",
                            "contacted",
                            "qualified",
                            "opportunity",
                            "won",
                            "lost",
                            "unqualified"
                        ]
                    },
                    "stage_label": {
                        "type": "string",
                        "description": "The stage as people read it, e.g. \"Qualified\"."
                    },
                    "closed": {
                        "type": "boolean",
                        "description": "True when the stage is won, lost or unqualified."
                    },
                    "archived": {
                        "type": "boolean",
                        "description": "True when the lead was archived; archived leads are left out of default lists."
                    },
                    "labels": {
                        "type": "array",
                        "description": "The lead's labels, alphabetically.",
                        "items": {
                            "type": "object",
                            "description": "A label on the lead.",
                            "properties": {
                                "id": {
                                    "type": "integer",
                                    "description": "Label id."
                                },
                                "name": {
                                    "type": "string",
                                    "description": "Label name."
                                },
                                "color": {
                                    "type": "string",
                                    "description": "Hex colour, e.g. #e11d48."
                                }
                            }
                        }
                    },
                    "interest": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What they want to buy."
                    },
                    "estimated_value": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "Expected deal size in the currency's main unit (4500000 = TSh 4.5M)."
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO 4217 code of estimated_value; the workspace's own currency unless set."
                    },
                    "score": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How likely they are to buy, 0\u2013100.",
                        "minimum": 0,
                        "maximum": 100
                    },
                    "source_channel": {
                        "type": "string",
                        "description": "Where the lead first came from.",
                        "enum": [
                            "call",
                            "whatsapp",
                            "sms",
                            "messenger",
                            "instagram",
                            "tiktok",
                            "email",
                            "comment",
                            "form",
                            "web",
                            "chat",
                            "manual",
                            "import",
                            "api"
                        ]
                    },
                    "assigned_to": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The team member who looks after the lead; null while it waits in the unassigned pool.",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "Team member id."
                            },
                            "name": {
                                "type": "string",
                                "description": "Their name."
                            }
                        }
                    },
                    "next_action": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The next thing to do, e.g. \"Send quote\"."
                    },
                    "next_action_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the next action is due.",
                        "format": "date-time"
                    },
                    "overdue": {
                        "type": "boolean",
                        "description": "True when next_action_at has passed and the lead is still open."
                    },
                    "created_by": {
                        "type": "object",
                        "description": "Who added the lead.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "user, ai, mcp, api, flow, form, import or system.",
                                "enum": [
                                    "user",
                                    "ai",
                                    "mcp",
                                    "api",
                                    "flow",
                                    "form",
                                    "import",
                                    "system"
                                ]
                            },
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The person, AI agent or credential id behind that kind, when there is one."
                            }
                        }
                    },
                    "last_activity_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The last time anything happened on the lead.",
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the lead was added.",
                        "format": "date-time"
                    }
                }
            },
            "LeadSourceRef": {
                "type": "object",
                "description": "One record the lead is attached to \u2014 the calls, chats, comments and form answers it came through. Exactly one is the origin.",
                "properties": {
                    "kind": {
                        "type": "string",
                        "description": "What the lead is attached to.",
                        "enum": [
                            "call",
                            "conversation",
                            "comment",
                            "form_answer",
                            "email",
                            "contact"
                        ]
                    },
                    "id": {
                        "type": "string",
                        "description": "That record's id, as a string: a call id is the one `GET /api/v3/\u2026` call endpoints use, a conversation id the inbox's."
                    },
                    "channel": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The channel of that record: whatsapp, sms, instagram, call\u2026"
                    },
                    "title": {
                        "type": "string",
                        "description": "The record as people read it, e.g. \"WhatsApp chat\" or \"Call\"."
                    },
                    "url": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Where the record opens in the dashboard (a path on the account's host), when it has a page."
                    },
                    "call": {
                        "type": "object",
                        "description": "Only for calls: the call at a glance.",
                        "properties": {
                            "direction": {
                                "type": "string",
                                "description": "inbound or outbound."
                            },
                            "duration_seconds": {
                                "type": "integer",
                                "description": "How long the call lasted."
                            },
                            "started_at": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "When it started.",
                                "format": "date-time"
                            },
                            "outcome": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "answered, no_answer, busy\u2026"
                            },
                            "has_recording": {
                                "type": "boolean",
                                "description": "Whether a recording exists."
                            }
                        }
                    },
                    "is_origin": {
                        "type": "boolean",
                        "description": "True for the record the lead was first created from."
                    },
                    "first_seen_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the record was attached.",
                        "format": "date-time"
                    },
                    "last_seen_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The last time the lead was touched through it.",
                        "format": "date-time"
                    }
                }
            },
            "Lead": {
                "type": "object",
                "description": "One person's sales record, at any stage, with where it came from.",
                "required": [
                    "id",
                    "title",
                    "stage",
                    "closed",
                    "labels",
                    "currency",
                    "source_channel",
                    "sources"
                ],
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The lead's id (a uuid). Use it in every /leads/{lead} path.",
                        "format": "uuid"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The person's name, as given."
                    },
                    "title": {
                        "type": "string",
                        "description": "What to show as the lead's title: the name, else the company, phone or email."
                    },
                    "company": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Their business, if they gave one."
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Phone number in E.164 (+255\u2026)."
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Email address, lowercased."
                    },
                    "stage": {
                        "type": "string",
                        "description": "Where the lead is in the pipeline. won, lost and unqualified close it.",
                        "enum": [
                            "new",
                            "contacted",
                            "qualified",
                            "opportunity",
                            "won",
                            "lost",
                            "unqualified"
                        ]
                    },
                    "stage_label": {
                        "type": "string",
                        "description": "The stage as people read it, e.g. \"Qualified\"."
                    },
                    "closed": {
                        "type": "boolean",
                        "description": "True when the stage is won, lost or unqualified."
                    },
                    "archived": {
                        "type": "boolean",
                        "description": "True when the lead was archived; archived leads are left out of default lists."
                    },
                    "labels": {
                        "type": "array",
                        "description": "The lead's labels, alphabetically.",
                        "items": {
                            "type": "object",
                            "description": "A label on the lead.",
                            "properties": {
                                "id": {
                                    "type": "integer",
                                    "description": "Label id."
                                },
                                "name": {
                                    "type": "string",
                                    "description": "Label name."
                                },
                                "color": {
                                    "type": "string",
                                    "description": "Hex colour, e.g. #e11d48."
                                }
                            }
                        }
                    },
                    "interest": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What they want to buy."
                    },
                    "estimated_value": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "Expected deal size in the currency's main unit (4500000 = TSh 4.5M)."
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO 4217 code of estimated_value; the workspace's own currency unless set."
                    },
                    "score": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How likely they are to buy, 0\u2013100.",
                        "minimum": 0,
                        "maximum": 100
                    },
                    "source_channel": {
                        "type": "string",
                        "description": "Where the lead first came from.",
                        "enum": [
                            "call",
                            "whatsapp",
                            "sms",
                            "messenger",
                            "instagram",
                            "tiktok",
                            "email",
                            "comment",
                            "form",
                            "web",
                            "chat",
                            "manual",
                            "import",
                            "api"
                        ]
                    },
                    "assigned_to": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The team member who looks after the lead; null while it waits in the unassigned pool.",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "Team member id."
                            },
                            "name": {
                                "type": "string",
                                "description": "Their name."
                            }
                        }
                    },
                    "next_action": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The next thing to do, e.g. \"Send quote\"."
                    },
                    "next_action_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the next action is due.",
                        "format": "date-time"
                    },
                    "overdue": {
                        "type": "boolean",
                        "description": "True when next_action_at has passed and the lead is still open."
                    },
                    "created_by": {
                        "type": "object",
                        "description": "Who added the lead.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "user, ai, mcp, api, flow, form, import or system.",
                                "enum": [
                                    "user",
                                    "ai",
                                    "mcp",
                                    "api",
                                    "flow",
                                    "form",
                                    "import",
                                    "system"
                                ]
                            },
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The person, AI agent or credential id behind that kind, when there is one."
                            }
                        }
                    },
                    "last_activity_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The last time anything happened on the lead.",
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the lead was added.",
                        "format": "date-time"
                    },
                    "location": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Area or city."
                    },
                    "summary": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A short account of what they need \u2014 often written by the AI agent."
                    },
                    "score_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the score is what it is."
                    },
                    "source_detail": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A human line about the origin, e.g. \"Called 0800 110 110\" or \"Ad: October promo\"."
                    },
                    "source_meta": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Machine detail about the origin: the ad a chat started from, the number dialled.",
                        "additionalProperties": true
                    },
                    "lost_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why the lead was lost or disqualified."
                    },
                    "custom_fields": {
                        "type": "object",
                        "description": "Values of the workspace's custom fields, keyed by field key (see `GET /api/v3/lead-fields`).",
                        "additionalProperties": true
                    },
                    "missing_fields": {
                        "type": "array",
                        "description": "Labels of required custom fields that are still empty.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "stage_changed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the stage last changed.",
                        "format": "date-time"
                    },
                    "closed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the lead was won, lost or disqualified; null while open.",
                        "format": "date-time"
                    },
                    "archived_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When the lead was archived.",
                        "format": "date-time"
                    },
                    "last_contacted_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The last time the customer and the business were in touch through an attached record.",
                        "format": "date-time"
                    },
                    "identities": {
                        "type": "array",
                        "description": "Every way this person is known in the workspace \u2014 the identity layer that makes dedupe work.",
                        "items": {
                            "type": "object",
                            "description": "One identifier.",
                            "properties": {
                                "kind": {
                                    "type": "string",
                                    "description": "phone, whatsapp, email, social or customer."
                                },
                                "value": {
                                    "type": "string",
                                    "description": "The normalised value: digits for phones, network:id for social."
                                }
                            }
                        }
                    },
                    "sources": {
                        "type": "array",
                        "description": "What the lead is attached to, origin first.",
                        "items": {
                            "$ref": "#/components/schemas/LeadSourceRef"
                        }
                    },
                    "possible_duplicate": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Another lead that looks like the same person. Merge it in the dashboard.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The other lead's id.",
                                "format": "uuid"
                            },
                            "title": {
                                "type": "string",
                                "description": "Its title."
                            },
                            "stage": {
                                "type": "string",
                                "description": "Its stage."
                            }
                        }
                    }
                }
            },
            "LeadActivity": {
                "type": "object",
                "description": "One line of a lead's timeline. The timeline is append-only; a removed note keeps its line and loses its text.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Activity id; pass it as `before` to read further back."
                    },
                    "type": {
                        "type": "string",
                        "description": "What happened.",
                        "enum": [
                            "created",
                            "updated",
                            "stage_changed",
                            "label_added",
                            "label_removed",
                            "note",
                            "assigned",
                            "source_attached",
                            "merged",
                            "archived",
                            "restored",
                            "deleted"
                        ]
                    },
                    "changes": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "For changes: `{field: {from, to}}`.",
                        "additionalProperties": true
                    },
                    "body": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The note text, or the reason given for a stage change. Null for a removed note."
                    },
                    "redacted": {
                        "type": "boolean",
                        "description": "True for a note someone removed."
                    },
                    "actor": {
                        "type": "object",
                        "description": "Who did it.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "user, ai, mcp, api, flow, form, import or system.",
                                "enum": [
                                    "user",
                                    "ai",
                                    "mcp",
                                    "api",
                                    "flow",
                                    "form",
                                    "import",
                                    "system"
                                ]
                            },
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The person, AI agent or credential id, when there is one."
                            },
                            "label": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Their name at the time, e.g. \"Mauzo AI\" or \"Baraka M.\"."
                            }
                        }
                    },
                    "source": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The call or conversation it happened in, if any.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "What the lead is attached to.",
                                "enum": [
                                    "call",
                                    "conversation",
                                    "comment",
                                    "form_answer",
                                    "email",
                                    "contact"
                                ]
                            },
                            "id": {
                                "type": "string",
                                "description": "That record's id, as a string: a call id is the one `GET /api/v3/\u2026` call endpoints use, a conversation id the inbox's."
                            },
                            "channel": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The channel of that record: whatsapp, sms, instagram, call\u2026"
                            },
                            "title": {
                                "type": "string",
                                "description": "The record as people read it, e.g. \"WhatsApp chat\" or \"Call\"."
                            },
                            "url": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Where the record opens in the dashboard (a path on the account's host), when it has a page."
                            }
                        }
                    },
                    "engine_run_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "For AI changes: the AI run that made it."
                    },
                    "meta": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "Extra facts, e.g. `{\"unverified\": {\"email\": \"heard_on_call\"}}` when the AI heard a detail on a call it could not confirm.",
                        "additionalProperties": true
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it happened.",
                        "format": "date-time"
                    }
                }
            },
            "LeadLabel": {
                "type": "object",
                "description": "One of the workspace's lead labels.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "Label id."
                    },
                    "name": {
                        "type": "string",
                        "description": "The name; unique in the workspace regardless of case."
                    },
                    "color": {
                        "type": "string",
                        "description": "Hex colour, #rrggbb."
                    },
                    "description": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When to use it. The AI agent reads this to pick the right label."
                    },
                    "ai_assignable": {
                        "type": "boolean",
                        "description": "Whether the AI agent may put this label on a lead."
                    },
                    "created_by_kind": {
                        "type": "string",
                        "description": "Who made it: user, ai, api or system (the defaults)."
                    },
                    "leads_count": {
                        "type": "integer",
                        "description": "How many leads carry it."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was made.",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed.",
                        "format": "date-time"
                    }
                }
            },
            "LeadField": {
                "type": "object",
                "description": "A custom field the workspace defined for its leads. Send values in a lead's `custom_fields` under `key`.",
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The key to use in `custom_fields`."
                    },
                    "label": {
                        "type": "string",
                        "description": "The field as people read it."
                    },
                    "type": {
                        "type": "string",
                        "description": "The value type; values are validated like a Daftari column of the same type.",
                        "enum": [
                            "text",
                            "long_text",
                            "number",
                            "currency",
                            "boolean",
                            "date",
                            "datetime",
                            "phone",
                            "email",
                            "select",
                            "multi_select"
                        ]
                    },
                    "options": {
                        "type": [
                            "array",
                            "null"
                        ],
                        "description": "For select types: the allowed option keys.",
                        "items": {
                            "type": "object",
                            "description": "One option.",
                            "properties": {
                                "key": {
                                    "type": "string",
                                    "description": "Send this."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "People see this."
                                }
                            }
                        }
                    },
                    "required": {
                        "type": "boolean",
                        "description": "Required when a person edits the lead. Never blocks creating one."
                    },
                    "ai_writable": {
                        "type": "boolean",
                        "description": "Whether the AI agent may fill it."
                    },
                    "ai_hint": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the AI agent is told to put here."
                    },
                    "position": {
                        "type": "integer",
                        "description": "Display order."
                    }
                }
            },
            "LeadInput": {
                "type": "object",
                "description": "A lead to create or update. Send at least one of phone, email or name, or a conversation_id / call_id. Empty values are ignored on an upsert \u2014 it never blanks a field.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The person's name.",
                        "maxLength": 160
                    },
                    "phone": {
                        "type": "string",
                        "description": "Their phone number in any common form \u2014 0712 345 678, 712345678, +255 712 345 678. Stored as E.164.",
                        "maxLength": 40
                    },
                    "email": {
                        "type": "string",
                        "description": "Their email address.",
                        "maxLength": 191
                    },
                    "company": {
                        "type": "string",
                        "description": "Their business.",
                        "maxLength": 160
                    },
                    "location": {
                        "type": "string",
                        "description": "Area or city.",
                        "maxLength": 160
                    },
                    "interest": {
                        "type": "string",
                        "description": "What they want to buy.",
                        "maxLength": 255
                    },
                    "estimated_value": {
                        "type": "number",
                        "description": "Expected deal size in the currency's main unit (4500000 = TSh 4.5M).",
                        "minimum": 0
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO 4217 code, e.g. TZS. Defaults to the workspace's currency.",
                        "minLength": 3,
                        "maxLength": 3
                    },
                    "score": {
                        "type": "integer",
                        "description": "How likely they are to buy, 0\u2013100.",
                        "minimum": 0,
                        "maximum": 100
                    },
                    "score_reason": {
                        "type": "string",
                        "description": "Why that score.",
                        "maxLength": 500
                    },
                    "summary": {
                        "type": "string",
                        "description": "A short account of what they need.",
                        "maxLength": 1000
                    },
                    "next_action": {
                        "type": "string",
                        "description": "The next thing to do.",
                        "maxLength": 255
                    },
                    "next_action_at": {
                        "type": "string",
                        "description": "When it is due, ISO 8601. A time with no offset is read in the workspace's timezone.",
                        "format": "date-time"
                    },
                    "source_detail": {
                        "type": "string",
                        "description": "A human line about where the lead came from, e.g. \"Trade fair, Mlimani City\".",
                        "maxLength": 255
                    },
                    "custom_fields": {
                        "type": "object",
                        "description": "Custom field values keyed by field key from `GET /api/v3/lead-fields`.",
                        "additionalProperties": true
                    },
                    "stage": {
                        "type": "string",
                        "description": "Put the lead in this stage. lost and unqualified need `reason`.",
                        "enum": [
                            "new",
                            "contacted",
                            "qualified",
                            "opportunity",
                            "won",
                            "lost",
                            "unqualified"
                        ]
                    },
                    "reason": {
                        "type": "string",
                        "description": "Why \u2014 required when stage is lost or unqualified.",
                        "maxLength": 255
                    },
                    "labels": {
                        "type": "array",
                        "description": "Label names to add. A name that does not exist yet is created only if the key's issuer holds leads.settings; otherwise it comes back in `refused`.",
                        "maxItems": 20,
                        "items": {
                            "type": "string",
                            "maxLength": 64
                        }
                    },
                    "note": {
                        "type": "string",
                        "description": "A note to write on the timeline.",
                        "maxLength": 2000
                    },
                    "conversation_id": {
                        "type": "integer",
                        "description": "Attach this inbox conversation. The customer is then identified by the conversation itself."
                    },
                    "call_id": {
                        "type": "integer",
                        "description": "Attach this call. The customer is the other party on the call."
                    },
                    "assigned_to": {
                        "type": "integer",
                        "description": "Give a new lead to this team member (needs leads.assign). Without it a lead lands in the unassigned pool, or with the workspace's default owner."
                    }
                }
            },
            "LeadCaptureResult": {
                "type": "object",
                "description": "What an upsert did.",
                "properties": {
                    "lead": {
                        "$ref": "#/components/schemas/Lead",
                        "description": "The lead as it is now."
                    },
                    "created": {
                        "type": "boolean",
                        "description": "True when this call created the lead (HTTP 201); false when it matched an existing one (200)."
                    },
                    "was_closed": {
                        "type": "boolean",
                        "description": "True when the matched lead was already won, lost or unqualified. Its stage is not changed unless you sent one."
                    },
                    "ignored": {
                        "type": "array",
                        "description": "Fields that were not applied, and why.",
                        "items": {
                            "type": "object",
                            "description": "One ignored field.",
                            "properties": {
                                "field": {
                                    "type": "string",
                                    "description": "The field."
                                },
                                "reason": {
                                    "type": "string",
                                    "description": "A code: invalid, reason_required, won_locked\u2026"
                                },
                                "message": {
                                    "type": "string",
                                    "description": "What to do about it."
                                }
                            }
                        }
                    },
                    "refused": {
                        "type": "array",
                        "description": "Labels that were not applied, and why.",
                        "items": {
                            "type": "object",
                            "description": "One refused label.",
                            "properties": {
                                "label": {
                                    "type": "string",
                                    "description": "The label name."
                                },
                                "reason": {
                                    "type": "string",
                                    "description": "label_unknown (no such label, and the issuer may not create one) or label_not_available."
                                }
                            }
                        }
                    },
                    "possible_duplicate_of": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Another lead that looks like the same person (its id). Merge it in the dashboard.",
                        "format": "uuid"
                    }
                }
            },
            "LeadWebhookSnapshot": {
                "type": "object",
                "description": "The full lead a `lead.*` webhook carries, so a receiver can upsert it without calling back.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Lead id (uuid).",
                        "format": "uuid"
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Name."
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Phone, E.164."
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Email."
                    },
                    "company": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Company."
                    },
                    "location": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Area or city."
                    },
                    "stage": {
                        "type": "string",
                        "description": "Stage.",
                        "enum": [
                            "new",
                            "contacted",
                            "qualified",
                            "opportunity",
                            "won",
                            "lost",
                            "unqualified"
                        ]
                    },
                    "closed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it closed; null while open.",
                        "format": "date-time"
                    },
                    "archived_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was archived.",
                        "format": "date-time"
                    },
                    "lost_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it was lost or disqualified."
                    },
                    "source_channel": {
                        "type": "string",
                        "description": "Where it first came from.",
                        "enum": [
                            "call",
                            "whatsapp",
                            "sms",
                            "messenger",
                            "instagram",
                            "tiktok",
                            "email",
                            "comment",
                            "form",
                            "web",
                            "chat",
                            "manual",
                            "import",
                            "api"
                        ]
                    },
                    "source_detail": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A human line about the origin."
                    },
                    "interest": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What they want."
                    },
                    "estimated_value": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "Deal size, main units."
                    },
                    "currency": {
                        "type": "string",
                        "description": "ISO 4217 code."
                    },
                    "score": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Score 0\u2013100."
                    },
                    "score_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why that score."
                    },
                    "summary": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What they need."
                    },
                    "next_action": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Next thing to do."
                    },
                    "next_action_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it is due.",
                        "format": "date-time"
                    },
                    "labels": {
                        "type": "array",
                        "description": "Label names.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "assigned_to": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The team member who looks after the lead; null while it waits in the unassigned pool.",
                        "properties": {
                            "id": {
                                "type": "integer",
                                "description": "Team member id."
                            },
                            "name": {
                                "type": "string",
                                "description": "Their name."
                            }
                        }
                    },
                    "custom_fields": {
                        "type": "object",
                        "description": "Custom field values by key.",
                        "additionalProperties": true
                    },
                    "created_by": {
                        "type": "object",
                        "description": "Who added the lead.",
                        "properties": {
                            "kind": {
                                "type": "string",
                                "description": "user, ai, mcp, api, flow, form, import or system.",
                                "enum": [
                                    "user",
                                    "ai",
                                    "mcp",
                                    "api",
                                    "flow",
                                    "form",
                                    "import",
                                    "system"
                                ]
                            },
                            "id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "The person, AI agent or credential id behind that kind, when there is one."
                            }
                        }
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was added.",
                        "format": "date-time"
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed.",
                        "format": "date-time"
                    },
                    "url": {
                        "type": "string",
                        "description": "The lead's page in the dashboard.",
                        "format": "uri"
                    }
                }
            },
            "WhatsAppFormAccount": {
                "type": "object",
                "description": "One WhatsApp business account of the workspace, as a form sees it. WhatsApp keeps a form on one account and refuses to send it from a number on another, so a form has a home account (where its working copy and previews live) and may be added to others; each added account gets its own copy of every published version.",
                "properties": {
                    "waba_id": {
                        "type": "string",
                        "description": "The account's id.",
                        "example": "102290129340398"
                    },
                    "name": {
                        "type": "string",
                        "description": "The account's business name.",
                        "example": "Duka la Pili"
                    },
                    "numbers": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "The account's phone numbers, as WhatsApp shows them.",
                        "example": [
                            "+255 754 900 111"
                        ]
                    },
                    "role": {
                        "type": "string",
                        "enum": [
                            "home",
                            "added",
                            "available"
                        ],
                        "description": "`home`: where the form was made; `added`: the form is published here too; `available`: it could be added."
                    },
                    "live_status": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "WhatsApp's status of the live version on this account: PUBLISHED, THROTTLED, BLOCKED, DEPRECATED, or PENDING when it has not reached the account yet. Null when the form is not live or not on the account.",
                        "example": "PUBLISHED"
                    },
                    "sendable": {
                        "type": "boolean",
                        "description": "Whether a chat on this account's numbers can be sent the form now."
                    },
                    "error": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why WhatsApp did not accept the form on this account, when it did not."
                    },
                    "published_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the live version went live on this account."
                    }
                }
            },
            "WhatsAppTemplateCheckReport": {
                "type": "object",
                "description": "What the template checker found (Mlinzi): every rule WhatsApp holds a template to, checked before Meta sees it.",
                "required": [
                    "ready",
                    "counts",
                    "passed",
                    "issues"
                ],
                "properties": {
                    "ready": {
                        "type": "boolean",
                        "description": "False while anything would make WhatsApp refuse the template (a `block` issue)."
                    },
                    "counts": {
                        "type": "object",
                        "description": "How many issues of each level.",
                        "properties": {
                            "block": {
                                "type": "integer",
                                "description": "Findings that would make WhatsApp refuse the template."
                            },
                            "warn": {
                                "type": "integer",
                                "description": "Findings likely to get it refused, re-categorised, or to hurt the account."
                            },
                            "tip": {
                                "type": "integer",
                                "description": "Suggestions."
                            }
                        }
                    },
                    "passed": {
                        "type": "integer",
                        "description": "Checks that found nothing."
                    },
                    "issues": {
                        "type": "array",
                        "description": "Worst first.",
                        "items": {
                            "type": "object",
                            "required": [
                                "rule",
                                "level",
                                "message"
                            ],
                            "properties": {
                                "rule": {
                                    "type": "string",
                                    "description": "Stable rule id to key on, e.g. T-VAR-06 (a variable at the start or end)."
                                },
                                "level": {
                                    "type": "string",
                                    "enum": [
                                        "block",
                                        "warn",
                                        "tip"
                                    ],
                                    "description": "block: WhatsApp would refuse it. warn: likely refused, re-categorised, or bad for the account. tip: helps."
                                },
                                "field": {
                                    "type": [
                                        "string",
                                        "null"
                                    ],
                                    "description": "The part of the template it is about, e.g. body.text or buttons.1.url."
                                },
                                "message": {
                                    "type": "string",
                                    "description": "The finding in plain words, in the language of the key's user."
                                }
                            }
                        }
                    }
                }
            },
            "VoiceKeyPress": {
                "type": "object",
                "description": "One key the person pressed, in order.",
                "required": [
                    "digit",
                    "at"
                ],
                "properties": {
                    "digit": {
                        "type": "string",
                        "description": "The key: 0-9, * or #."
                    },
                    "action": {
                        "type": "string",
                        "description": "What the key was set to do (`repeat`, `confirm`, `agent`, \u2026), or what the PBX reported doing."
                    },
                    "label": {
                        "type": "string",
                        "description": "The label you gave the key, when you gave one."
                    },
                    "at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When it was pressed."
                    },
                    "event_id": {
                        "type": "string",
                        "description": "The call event that carried the press (deduplication)."
                    }
                }
            },
            "VoiceOtp": {
                "type": "object",
                "description": "A voice code call. The code itself is never returned or stored \u2014 only its length.",
                "required": [
                    "uid",
                    "type",
                    "status",
                    "to",
                    "language",
                    "repeat",
                    "code_length",
                    "keys_pressed",
                    "created_at"
                ],
                "properties": {
                    "uid": {
                        "type": "string",
                        "description": "`vc_\u2026` for a code, `vm_\u2026` for a message. What the status endpoint takes."
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "otp",
                            "message"
                        ],
                        "description": "`otp` (a voice code) or `message`."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "calling",
                            "answered",
                            "completed",
                            "failed",
                            "expired"
                        ],
                        "description": "`queued` (waiting for a line) \u2192 `calling` (ringing) \u2192 `answered` \u2192 `completed`; or `failed` (not answered, refused by the network, no money) / `expired` (a code whose time ran out before a line was free)."
                    },
                    "to": {
                        "type": "string",
                        "description": "The number rung, E.164."
                    },
                    "language": {
                        "type": "string",
                        "enum": [
                            "sw",
                            "en"
                        ],
                        "description": "The language spoken."
                    },
                    "repeat": {
                        "type": "integer",
                        "description": "For a code, how many times it is said in one go; for a message, how many times it plays."
                    },
                    "external_ref": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your reference, echoed on every webhook."
                    },
                    "outcome": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "How the call ended: `answered`, `no_answer`, `busy`, `declined`, `unavailable`, `unreachable`, `provider_failure`, \u2026; null while it is live."
                    },
                    "failure_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it failed: the call outcome (`no_answer`, `busy`, \u2026) or `expired`, `insufficient_balance`, `no_free_line`, `pbx_rejected`, `provider_failure`."
                    },
                    "keys_pressed": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/VoiceKeyPress"
                        },
                        "description": "Every key pressed, in order."
                    },
                    "talk_seconds": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How long the answered call lasted; 0 when it was not answered; null while live."
                    },
                    "estimated_cost": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "What one answered call was estimated to cost when it was queued (call minute and connect fee, plus first-time speech for a message), in the wallet currency."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the request was accepted."
                    },
                    "placed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the phone started ringing."
                    },
                    "answered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the person picked up."
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the answered call ended."
                    },
                    "failed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it failed or expired."
                    },
                    "code_length": {
                        "type": "integer",
                        "description": "How many digits the code had."
                    },
                    "voice_pack": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The voice pack it was said in (`sw-rehema-digits`, \u2026)."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "After this the call is no longer placed (status `expired`). Use the same window when you check the code."
                    }
                }
            },
            "VoiceMessage": {
                "type": "object",
                "description": "A voice message call.",
                "required": [
                    "uid",
                    "type",
                    "status",
                    "to",
                    "language",
                    "repeat",
                    "text",
                    "keys",
                    "tts",
                    "keys_pressed",
                    "created_at"
                ],
                "properties": {
                    "uid": {
                        "type": "string",
                        "description": "`vc_\u2026` for a code, `vm_\u2026` for a message. What the status endpoint takes."
                    },
                    "type": {
                        "type": "string",
                        "enum": [
                            "otp",
                            "message"
                        ],
                        "description": "`otp` (a voice code) or `message`."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "queued",
                            "calling",
                            "answered",
                            "completed",
                            "failed",
                            "expired"
                        ],
                        "description": "`queued` (waiting for a line) \u2192 `calling` (ringing) \u2192 `answered` \u2192 `completed`; or `failed` (not answered, refused by the network, no money) / `expired` (a code whose time ran out before a line was free)."
                    },
                    "to": {
                        "type": "string",
                        "description": "The number rung, E.164."
                    },
                    "language": {
                        "type": "string",
                        "enum": [
                            "sw",
                            "en"
                        ],
                        "description": "The language spoken."
                    },
                    "repeat": {
                        "type": "integer",
                        "description": "For a code, how many times it is said in one go; for a message, how many times it plays."
                    },
                    "external_ref": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your reference, echoed on every webhook."
                    },
                    "outcome": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "How the call ended: `answered`, `no_answer`, `busy`, `declined`, `unavailable`, `unreachable`, `provider_failure`, \u2026; null while it is live."
                    },
                    "failure_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why it failed: the call outcome (`no_answer`, `busy`, \u2026) or `expired`, `insufficient_balance`, `no_free_line`, `pbx_rejected`, `provider_failure`."
                    },
                    "keys_pressed": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/VoiceKeyPress"
                        },
                        "description": "Every key pressed, in order."
                    },
                    "talk_seconds": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "How long the answered call lasted; 0 when it was not answered; null while live."
                    },
                    "estimated_cost": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "What one answered call was estimated to cost when it was queued (call minute and connect fee, plus first-time speech for a message), in the wallet currency."
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When the request was accepted."
                    },
                    "placed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the phone started ringing."
                    },
                    "answered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the person picked up."
                    },
                    "completed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When the answered call ended."
                    },
                    "failed_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time",
                        "description": "When it failed or expired."
                    },
                    "text": {
                        "type": "string",
                        "description": "The words spoken."
                    },
                    "voice_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The voice they were spoken in (the provider's name for it)."
                    },
                    "model_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The speech model."
                    },
                    "keys": {
                        "type": "object",
                        "additionalProperties": {
                            "type": "object"
                        },
                        "description": "The keys as set: digit \u2192 `{action, label?}`."
                    },
                    "tts": {
                        "type": "object",
                        "description": "The speech generated for this message.",
                        "required": [
                            "characters",
                            "cached",
                            "cost"
                        ],
                        "properties": {
                            "characters": {
                                "type": "integer",
                                "description": "Characters in the text."
                            },
                            "cached": {
                                "type": "boolean",
                                "description": "True when these words in this voice were already generated, so nothing was charged."
                            },
                            "cost": {
                                "type": "number",
                                "description": "What generating the audio cost (0 when cached), in the wallet currency."
                            }
                        }
                    }
                }
            },
            "VoiceRefusalEnvelope": {
                "type": "object",
                "description": "A refusal the voice rules made (not a validation failure): the legacy error envelope plus a machine-readable `code` and, where there are facts, `details`.",
                "required": [
                    "status",
                    "message",
                    "code"
                ],
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "error"
                        ],
                        "description": "Always \"error\"."
                    },
                    "message": {
                        "type": "string",
                        "description": "Human-readable reason."
                    },
                    "code": {
                        "type": "string",
                        "enum": [
                            "invalid_number",
                            "country_not_allowed",
                            "rate_limited",
                            "insufficient_balance",
                            "no_caller_number",
                            "unknown_caller_number",
                            "unknown_voice_pack",
                            "voice_pack_not_ready",
                            "language_mismatch",
                            "code_too_long",
                            "unknown_voice",
                            "invalid_keys",
                            "opted_out",
                            "outside_calling_hours"
                        ],
                        "description": "What to branch on. `country_not_allowed` \u2014 `details.allowed_country_codes`; `rate_limited` (429) \u2014 the number already had 3 codes in 10 minutes, `details.retry_after` seconds (also the Retry-After header); `insufficient_balance` (402) \u2014 `details` carries `required`, `available`, `currency`; `no_caller_number` \u2014 the workspace has no number to call from; `unknown_voice_pack` / `voice_pack_not_ready` / `language_mismatch` \u2014 pick another pack or language; `code_too_long` \u2014 fewer digits or repeats; `unknown_voice` \u2014 no voice matches `voice_id`/`model_id`; `invalid_keys` \u2014 a key or action is not allowed. Voice messages only: `opted_out` \u2014 the person is on the do-not-call list; `outside_calling_hours` \u2014 `details.next_opening` (codes are exempt from both: the person asked for the code); `rate_limited` (429) also when a number had 5 voice messages in the last hour (configurable)."
                    },
                    "details": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Code-specific facts, present only when there are any."
                    }
                }
            },
            "CallKeyPressed": {
                "type": "object",
                "description": "A key the person pressed on a call, in order.",
                "properties": {
                    "digit": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The digit (0-9, *, #). Null when the phone system redacted it (PIN entry in an IVR)."
                    },
                    "action": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the key was set to do (confirm, tag, start_flow, opt_out \u2026), or the phone system's word for it when nothing was set."
                    },
                    "label": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The key's label, as set on the campaign or the API request."
                    },
                    "at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was pressed (ISO 8601)."
                    }
                },
                "required": [
                    "digit",
                    "action",
                    "label",
                    "at"
                ]
            },
            "Call": {
                "type": "object",
                "description": "One call of the workspace \u2014 inbound, outbound, a campaign call or one placed with POST /api/v3/calls.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The call id: GET /api/v3/calls/{id}."
                    },
                    "room_name": {
                        "type": "string",
                        "description": "The phone system's handle for the call."
                    },
                    "direction": {
                        "type": "string",
                        "description": "inbound or outbound."
                    },
                    "status": {
                        "type": "string",
                        "description": "Where the call is: ringing, in_progress, ended, missed, failed \u2026"
                    },
                    "outcome": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "How it ended, once it has: answered, no_answer, busy, declined, busy_or_declined, unavailable, unreachable, provider_failure, cancelled, billing_rejected, unknown."
                    },
                    "answered": {
                        "type": "boolean",
                        "description": "Someone (or the AI / IVR) picked up."
                    },
                    "from": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The calling number."
                    },
                    "to": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The number called."
                    },
                    "mode": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "message, ai or ivr for calls placed by the API or a campaign."
                    },
                    "agent_config_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The AI agent that talked, if any."
                    },
                    "source": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Who placed it: api, app, mcp, campaign, or the device / system for other calls."
                    },
                    "started_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it started ringing (ISO 8601)."
                    },
                    "answered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was answered."
                    },
                    "ended_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it ended."
                    },
                    "duration_seconds": {
                        "type": "integer",
                        "description": "How long it lasted."
                    },
                    "sip_status_code": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The carrier's SIP status, when the phone system saw one (486 busy, 480 unavailable \u2026)."
                    },
                    "keys_pressed": {
                        "type": "array",
                        "description": "Every key pressed, in order, with what it meant.",
                        "items": {
                            "$ref": "#/components/schemas/CallKeyPressed"
                        }
                    },
                    "recording_available": {
                        "type": "boolean",
                        "description": "A recording exists: GET /api/v3/calls/{id}/recordings."
                    },
                    "transcript_available": {
                        "type": "boolean",
                        "description": "A transcript exists: GET /api/v3/calls/{id}/transcript."
                    },
                    "request": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "What POST /api/v3/calls was asked for, when this call was placed that way; null otherwise.",
                        "properties": {
                            "external_ref": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Your own reference, as sent."
                            },
                            "purpose": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Why we are calling, as sent (AI calls)."
                            },
                            "variables": {
                                "type": "object",
                                "description": "The person's details, as sent.",
                                "additionalProperties": {
                                    "type": "string",
                                    "description": "A detail value."
                                }
                            },
                            "estimated_cost": {
                                "type": "number",
                                "description": "What one answered call was estimated to cost."
                            }
                        }
                    },
                    "campaign": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The campaign person this call was for, when it was a campaign call; null otherwise.",
                        "properties": {
                            "id": {
                                "type": "string",
                                "description": "The campaign id."
                            },
                            "name": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The campaign name."
                            },
                            "target_id": {
                                "type": "integer",
                                "description": "The person's row in the campaign."
                            },
                            "external_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "Your own id for the person, as sent."
                            },
                            "try": {
                                "type": "integer",
                                "description": "Which try this was."
                            },
                            "result": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The try's result: reached, pressed, no_answer, busy \u2026"
                            }
                        }
                    }
                },
                "required": [
                    "id",
                    "room_name",
                    "direction",
                    "status",
                    "outcome",
                    "answered",
                    "from",
                    "to",
                    "started_at",
                    "ended_at",
                    "duration_seconds",
                    "keys_pressed",
                    "recording_available",
                    "transcript_available",
                    "request",
                    "campaign"
                ]
            },
            "CallCampaignCounts": {
                "type": "object",
                "description": "The people of a campaign by result. They partition `all`; `reached_total` = reached + pressed.",
                "properties": {
                    "all": {
                        "type": "integer",
                        "description": "Everyone on the list."
                    },
                    "waiting": {
                        "type": "integer",
                        "description": "Not called yet."
                    },
                    "calling": {
                        "type": "integer",
                        "description": "On a call right now."
                    },
                    "reached": {
                        "type": "integer",
                        "description": "Heard the message or talked, no key."
                    },
                    "pressed": {
                        "type": "integer",
                        "description": "Pressed a key."
                    },
                    "pressed_by_digit": {
                        "type": "object",
                        "description": "How many pressed each digit.",
                        "additionalProperties": {
                            "type": "integer",
                            "description": "People who pressed this digit."
                        }
                    },
                    "reached_total": {
                        "type": "integer",
                        "description": "reached + pressed."
                    },
                    "callback": {
                        "type": "integer",
                        "description": "A call-back was booked; the next try is at that time."
                    },
                    "not_reached": {
                        "type": "integer",
                        "description": "Tried and not reached \u2014 awaiting another try, or out of tries."
                    },
                    "opted_out": {
                        "type": "integer",
                        "description": "Asked not to be called again (pressed 9, or told the AI)."
                    },
                    "wrong_number": {
                        "type": "integer",
                        "description": "The number is not in service."
                    },
                    "skipped": {
                        "type": "integer",
                        "description": "Not called: the campaign was stopped, or someone else answered a stop-on-answer list."
                    }
                }
            },
            "CallCampaign": {
                "type": "object",
                "description": "A call campaign: who, what, when, and how far it got.",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "The campaign id (UUID)."
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "What the business calls it."
                    },
                    "goal": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "payment_reminder, appointment, confirm_orders, announcement, survey, ai_conversation or blank."
                    },
                    "status": {
                        "type": "string",
                        "description": "draft, scheduled, running, paused, completed, cancelled or failed."
                    },
                    "state": {
                        "type": "string",
                        "description": "The owner's word for it: draft, scheduled, calling, paused, finished or stopped."
                    },
                    "state_label": {
                        "type": "string",
                        "description": "The state as the screens show it."
                    },
                    "needs_attention": {
                        "type": "boolean",
                        "description": "Paused because something on our side needs fixing (see attention_reason)."
                    },
                    "pause_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "manual, wallet_low (top up to continue; it resumes by itself), budget_cap or needs_attention."
                    },
                    "attention_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "pbx_unreachable, caller_number_disabled, agent_deleted, ivr_unpublished or message_invalid."
                    },
                    "mode": {
                        "type": "string",
                        "description": "message, ai or ivr."
                    },
                    "channel": {
                        "type": "string",
                        "description": "How people are rung: phone or whatsapp.",
                        "enum": [
                            "phone",
                            "whatsapp"
                        ]
                    },
                    "from_number": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The workspace's own number it calls from, E.164; null = the main line."
                    },
                    "is_rolling": {
                        "type": "boolean",
                        "description": "Always-on: stays open while people are added (targets/batch, an Automation); only cancel ends it."
                    },
                    "purpose_class": {
                        "type": "string",
                        "description": "transactional or marketing."
                    },
                    "source": {
                        "type": "string",
                        "description": "Where it was made: web, api, mcp, automation or app."
                    },
                    "external_ref": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your own reference; a create with the same one returns this campaign."
                    },
                    "people": {
                        "type": "integer",
                        "description": "Everyone on the list."
                    },
                    "counts": {
                        "$ref": "#/components/schemas/CallCampaignCounts",
                        "description": "The people by result."
                    },
                    "spent": {
                        "type": "number",
                        "description": "Money spent so far."
                    },
                    "held": {
                        "type": "number",
                        "description": "Money set aside from the wallet for the calls still to make."
                    },
                    "likely_cost": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "The estimate's likely cost, as last computed."
                    },
                    "currency": {
                        "type": "string",
                        "description": "Currency of spent, held and likely_cost."
                    },
                    "message": {
                        "type": "object",
                        "description": "What people hear (message mode).",
                        "properties": {
                            "text": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The message, with {placeholders} filled per person."
                            },
                            "audio_asset_id": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "A recording to play instead of the text."
                            },
                            "voice_id": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The voice the text is spoken in."
                            },
                            "voice_model": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The speech model."
                            },
                            "language": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "sw or en."
                            },
                            "repeat": {
                                "type": "integer",
                                "description": "How many times it plays when no key is pressed."
                            }
                        }
                    },
                    "keys": {
                        "type": "object",
                        "description": "Digit \u2192 what it does. 9 is always \"stop calling me\".",
                        "additionalProperties": {
                            "type": "object",
                            "description": "What pressing this digit does.",
                            "properties": {
                                "action": {
                                    "type": "string",
                                    "description": "confirm, ring_group, sms, tag, add_to_group, callback, repeat, agent, start_flow or opt_out. Live actions (repeat, ring_group, agent) happen on the call; the others happen in Momo after the key is reported.",
                                    "enum": [
                                        "confirm",
                                        "ring_group",
                                        "sms",
                                        "tag",
                                        "add_to_group",
                                        "callback",
                                        "repeat",
                                        "agent",
                                        "start_flow",
                                        "opt_out"
                                    ]
                                },
                                "label": {
                                    "type": "string",
                                    "description": "What the key means, in the business's words (\u2264 120 characters). Echoed on keys_pressed."
                                },
                                "say": {
                                    "type": "string",
                                    "description": "What the call says before acting on the key, e.g. \"Asante, tumepokea.\""
                                },
                                "ring_group_id": {
                                    "type": "integer",
                                    "description": "ring_group: the group to ring."
                                },
                                "agent_config_id": {
                                    "type": "string",
                                    "description": "agent: the AI agent to hand the person to (default: the campaign's)."
                                },
                                "text": {
                                    "type": "string",
                                    "description": "sms: the SMS sent to the person; {placeholders} are filled from their details."
                                },
                                "sender_id": {
                                    "type": "string",
                                    "description": "sms: the sender to send it from (default: the workspace's)."
                                },
                                "tag": {
                                    "type": "string",
                                    "description": "tag: the tag put on the person and their contact."
                                },
                                "contact_group_id": {
                                    "type": "integer",
                                    "description": "add_to_group: the contact group to add them to."
                                },
                                "group_name": {
                                    "type": "string",
                                    "description": "add_to_group: a group to create (or reuse) by name instead."
                                },
                                "flow_id": {
                                    "type": "integer",
                                    "description": "start_flow: the live WhatsApp flow started in the person's WhatsApp thread."
                                },
                                "answer": {
                                    "type": "object",
                                    "description": "Also record an answer on the person, e.g. {\"key\": \"interested\", \"value\": true}.",
                                    "properties": {
                                        "key": {
                                            "type": "string",
                                            "description": "The answer key."
                                        },
                                        "value": {
                                            "description": "The answer value."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "ivr_flow_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "The IVR flow, in ivr mode."
                    },
                    "agent_config_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The AI agent, in ai mode."
                    },
                    "answer_fields": {
                        "type": "array",
                        "description": "What the AI should find out on each call.",
                        "items": {
                            "type": "object",
                            "description": "One answer to find out.",
                            "properties": {
                                "key": {
                                    "type": "string",
                                    "description": "The answer key."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "What it is called."
                                },
                                "type": {
                                    "type": "string",
                                    "description": "text, number, date, boolean or choice."
                                }
                            }
                        }
                    },
                    "sms": {
                        "type": "object",
                        "description": "\"Send SMS from\".",
                        "properties": {
                            "sender": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The sender key every SMS of the campaign goes out from (\"sms:sender-id:12\"); null = the workspace's default sender when it sends."
                            }
                        }
                    },
                    "settings": {
                        "type": "object",
                        "description": "The effective settings.",
                        "properties": {
                            "calling_window": {
                                "type": "object",
                                "description": "When calls go out.",
                                "properties": {
                                    "timezone": {
                                        "type": "string",
                                        "description": "IANA timezone."
                                    },
                                    "days": {
                                        "type": "array",
                                        "description": "ISO weekdays.",
                                        "items": {
                                            "type": "integer",
                                            "description": "An ISO weekday."
                                        }
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Opening time."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Closing time."
                                    },
                                    "enforced": {
                                        "type": "boolean",
                                        "description": "Whether the hours are enforced."
                                    }
                                }
                            },
                            "max_tries": {
                                "type": "integer",
                                "description": "Tries per person."
                            },
                            "ring_seconds": {
                                "type": "integer",
                                "description": "How long each call rings."
                            },
                            "lines": {
                                "type": [
                                    "integer",
                                    "null"
                                ],
                                "description": "At most this many calls at once (null = the package's lines)."
                            },
                            "from_number": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "The caller number (null = the workspace's first)."
                            },
                            "stop_rule": {
                                "type": "string",
                                "description": "call_everyone, or stop_on_answer."
                            },
                            "max_call_seconds": {
                                "type": "integer",
                                "description": "The longest a call may last."
                            },
                            "record_calls": {
                                "type": "boolean",
                                "description": "Calls are recorded."
                            },
                            "cooldown_hours": {
                                "type": "integer",
                                "description": "People called by another campaign within this many hours are skipped."
                            },
                            "budget_cap": {
                                "type": [
                                    "number",
                                    "null"
                                ],
                                "description": "Stop spending past this amount."
                            }
                        }
                    },
                    "connections": {
                        "type": "object",
                        "description": "How results reach other modules: `daftari` {table, answers: {answer_key: column}, result_column?, summary_column?}, `leads` {answer_key, stage?, note}.",
                        "additionalProperties": true
                    },
                    "scheduled_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When a scheduled campaign starts."
                    },
                    "started_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it started calling."
                    },
                    "paused_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it paused."
                    },
                    "finished_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it finished, was stopped or failed."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it was made."
                    },
                    "updated_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When it last changed."
                    }
                }
            },
            "CallCampaignTarget": {
                "type": "object",
                "description": "One person of a campaign, with their result.",
                "properties": {
                    "id": {
                        "type": "integer",
                        "description": "The person's row id."
                    },
                    "position": {
                        "type": "integer",
                        "description": "Their place in the list (1-based): GET \u2026/targets?position=N starts there."
                    },
                    "to": {
                        "type": "string",
                        "description": "The number called (E.164)."
                    },
                    "name": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Their name."
                    },
                    "external_id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Your own id for them (an order, a loan, a Daftari record, a lead)."
                    },
                    "contact_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Their contact, when they came from a contact group."
                    },
                    "result": {
                        "type": "string",
                        "description": "waiting, calling, reached, pressed, no_answer, busy, switched_off, voicemail, declined, wrong_number, opted_out, our_problem, callback, not_reached or skipped."
                    },
                    "result_label": {
                        "type": "string",
                        "description": "The result in words: \"Pressed 1\", \"No answer\" \u2026"
                    },
                    "skip_reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why they were skipped, when result is skipped: whatsapp_permission_required (a WhatsApp campaign, and they have not allowed WhatsApp calls from the business; never retried), dispatch_failed, or callback_<status> for a call-back that was cancelled. Null otherwise."
                    },
                    "final": {
                        "type": "boolean",
                        "description": "Nothing more will happen for this person."
                    },
                    "tries": {
                        "type": "integer",
                        "description": "Calls that counted as a try."
                    },
                    "max_tries": {
                        "type": "integer",
                        "description": "Tries allowed."
                    },
                    "next_try_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When they will be tried again."
                    },
                    "keys_pressed": {
                        "type": "array",
                        "description": "Digits pressed, in order.",
                        "items": {
                            "type": "string",
                            "description": "A digit."
                        }
                    },
                    "answers": {
                        "type": "object",
                        "description": "What they answered: confirmed, interested, an AI answer field, tags \u2026",
                        "additionalProperties": true
                    },
                    "summary": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "The AI's one-line summary of them."
                    },
                    "variables": {
                        "type": "object",
                        "description": "Their details, as sent ({jina}, {kiasi} \u2026).",
                        "additionalProperties": {
                            "type": "string",
                            "description": "A detail value."
                        }
                    },
                    "last_call_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "description": "Their latest call: GET /api/v3/calls/{id}."
                    },
                    "last_call_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When they were last called."
                    },
                    "cost": {
                        "type": "number",
                        "description": "What their calls cost."
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "When they were added."
                    }
                }
            },
            "CallCampaignPayload": {
                "type": "object",
                "description": "The campaign composer payload \u2014 the one shape the web composer, MCP, Automations and this API send. On create, anything left out takes the goal's defaults; on PATCH, only what is sent changes.",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "What to call the campaign (\u2264 120)."
                    },
                    "goal": {
                        "type": "string",
                        "description": "payment_reminder, appointment, confirm_orders, announcement, survey, ai_conversation or blank \u2014 fills the defaults (mode, cooldown \u2026).",
                        "enum": [
                            "payment_reminder",
                            "appointment",
                            "confirm_orders",
                            "announcement",
                            "survey",
                            "ai_conversation",
                            "blank"
                        ]
                    },
                    "purpose_class": {
                        "type": "string",
                        "description": "transactional or marketing (marketing gets stricter defaults).",
                        "enum": [
                            "transactional",
                            "marketing"
                        ]
                    },
                    "audience": {
                        "type": "object",
                        "description": "Who to call. Every source is cleaned the same way: numbers normalised to +255, duplicates, invalid numbers, do-not-call and the cooldown removed.",
                        "properties": {
                            "type": {
                                "type": "string",
                                "description": "group, paste, targets, daftari or leads.",
                                "enum": [
                                    "group",
                                    "paste",
                                    "targets",
                                    "daftari",
                                    "leads"
                                ]
                            },
                            "contact_group_id": {
                                "type": "integer",
                                "description": "group: the contact group."
                            },
                            "text": {
                                "type": "string",
                                "description": "paste: numbers and names, one per line (\"0712 000 001, Amina\")."
                            },
                            "targets": {
                                "type": "array",
                                "description": "targets: the people, each with their own details and your id.",
                                "items": {
                                    "type": "object",
                                    "description": "One person.",
                                    "properties": {
                                        "to": {
                                            "type": "string",
                                            "description": "Their number, international or local."
                                        },
                                        "name": {
                                            "type": "string",
                                            "description": "Their name."
                                        },
                                        "variables": {
                                            "type": "object",
                                            "description": "Their details for the message and the agent ({kiasi}, {tarehe} \u2026): names of letters, digits and _.",
                                            "additionalProperties": {
                                                "type": "string",
                                                "description": "A detail value."
                                            }
                                        },
                                        "external_id": {
                                            "type": "string",
                                            "description": "Your id for them (\u2264 128): echoed on results and webhooks; targets/batch never adds the same one twice."
                                        }
                                    }
                                }
                            },
                            "table": {
                                "type": "string",
                                "description": "daftari: the data table id (needs data.view and read access to the table)."
                            },
                            "filter": {
                                "type": "object",
                                "description": "daftari: a filter over the table, {\"all\": [{\"column\": \"status\", \"op\": \"equals\", \"value\": \"overdue\"}]}.",
                                "additionalProperties": true
                            },
                            "phone_column": {
                                "type": "string",
                                "description": "daftari: the column with the number (default: the table's phone column)."
                            },
                            "name_column": {
                                "type": "string",
                                "description": "daftari: the column with the name."
                            },
                            "variables": {
                                "type": "array",
                                "description": "daftari: the columns to pass as details (default: all).",
                                "items": {
                                    "type": "string",
                                    "description": "A column key."
                                }
                            },
                            "stages": {
                                "type": "array",
                                "description": "leads: the lead stages to call \u2014 open leads with a phone that the key's issuer may see (needs leads.view).",
                                "items": {
                                    "type": "string",
                                    "description": "new, contacted, qualified, opportunity \u2026"
                                }
                            }
                        }
                    },
                    "mode": {
                        "type": "string",
                        "description": "message (a spoken or recorded message with keys), ai (an AI agent talks) or ivr (an IVR flow).",
                        "enum": [
                            "message",
                            "ai",
                            "ivr"
                        ]
                    },
                    "channel": {
                        "type": "string",
                        "description": "How people are rung: phone (a phone call, the default) or whatsapp (a WhatsApp call). WhatsApp needs mode ai and one of the workspace's lines that is on WhatsApp; only people who allowed WhatsApp calls from the business can be reached, and the rest are skipped (skip_reason whatsapp_permission_required), never retried.",
                        "enum": [
                            "phone",
                            "whatsapp"
                        ],
                        "default": "phone"
                    },
                    "from_number": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Which of the workspace's own numbers to call from, E.164. Left out: the main line (on WhatsApp, the first line that is on WhatsApp). It must be a line the key's issuer may call from.",
                        "example": "+255754000777"
                    },
                    "message": {
                        "type": "object",
                        "description": "message mode: what people hear.",
                        "properties": {
                            "text": {
                                "type": "string",
                                "description": "The message (\u2264 2000), {placeholders} filled from each person's details; {biashara} is the business name. A detail a person has no value for is left out cleanly (\"Habari {jina},\" \u2192 \"Habari,\"); {jina|mteja} says \"mteja\" instead. A goal template marks the part you write as [[\u2026]] (e.g. [[Andika tangazo lako hapa]]): it is never spoken, and a campaign is refused (message.text) until it is replaced."
                            },
                            "audio_asset_id": {
                                "type": "integer",
                                "description": "A published recording to play instead."
                            },
                            "voice_id": {
                                "type": "string",
                                "description": "The voice: one of that model's voices (catalogue id or name, e.g. \"Kore\"), or a voice pack persona such as \"rehema\". Left out: the model's default voice. A voice of another model is refused (message.voice_id)."
                            },
                            "voice_model": {
                                "type": "string",
                                "description": "The speech model the text is said with: the id or name of an enabled text-to-speech model of the catalogue (the Asset Studio list). Left out: the default, Gemini 2.5 Flash TTS. A Gemini model is spoken live on each call; another provider's model is made into audio for each person just before their call, charged per character."
                            },
                            "language": {
                                "type": "string",
                                "description": "sw or en."
                            },
                            "repeat": {
                                "type": "integer",
                                "description": "Plays (1-3) when no key is pressed."
                            }
                        }
                    },
                    "keys": {
                        "type": "object",
                        "description": "Digit \u2192 what pressing it does. 9 is always \"stop calling me\" and cannot be changed.",
                        "additionalProperties": {
                            "type": "object",
                            "description": "What pressing this digit does.",
                            "properties": {
                                "action": {
                                    "type": "string",
                                    "description": "confirm, ring_group, sms, tag, add_to_group, callback, repeat, agent, start_flow or opt_out. Live actions (repeat, ring_group, agent) happen on the call; the others happen in Momo after the key is reported.",
                                    "enum": [
                                        "confirm",
                                        "ring_group",
                                        "sms",
                                        "tag",
                                        "add_to_group",
                                        "callback",
                                        "repeat",
                                        "agent",
                                        "start_flow",
                                        "opt_out"
                                    ]
                                },
                                "label": {
                                    "type": "string",
                                    "description": "What the key means, in the business's words (\u2264 120 characters). Echoed on keys_pressed."
                                },
                                "say": {
                                    "type": "string",
                                    "description": "What the call says before acting on the key, e.g. \"Asante, tumepokea.\""
                                },
                                "ring_group_id": {
                                    "type": "integer",
                                    "description": "ring_group: the group to ring."
                                },
                                "agent_config_id": {
                                    "type": "string",
                                    "description": "agent: the AI agent to hand the person to (default: the campaign's)."
                                },
                                "text": {
                                    "type": "string",
                                    "description": "sms: the SMS sent to the person; {placeholders} are filled from their details."
                                },
                                "sender_id": {
                                    "type": "string",
                                    "description": "Older clients: the sender for the whole campaign, read as sms.sender (which wins when both are sent). A campaign sends every SMS from one sender.",
                                    "deprecated": true
                                },
                                "tag": {
                                    "type": "string",
                                    "description": "tag: the tag put on the person and their contact."
                                },
                                "contact_group_id": {
                                    "type": "integer",
                                    "description": "add_to_group: the contact group to add them to."
                                },
                                "group_name": {
                                    "type": "string",
                                    "description": "add_to_group: a group to create (or reuse) by name instead."
                                },
                                "flow_id": {
                                    "type": "integer",
                                    "description": "start_flow: the live WhatsApp flow started in the person's WhatsApp thread."
                                },
                                "answer": {
                                    "type": "object",
                                    "description": "Also record an answer on the person, e.g. {\"key\": \"interested\", \"value\": true}.",
                                    "properties": {
                                        "key": {
                                            "type": "string",
                                            "description": "The answer key."
                                        },
                                        "value": {
                                            "description": "The answer value."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "sms": {
                        "type": "object",
                        "description": "\"Send SMS from\": the one sender every SMS of this campaign goes out from \u2014 the \"sms\" keys, the automatic SMS to the people not reached (advanced.fallback_sms) and, unless another is chosen then, \"SMS the people not reached\" after it. Left out: the workspace's default sender when it sends (its own approved sender ID, else the platform default RMNDR).",
                        "properties": {
                            "sender": {
                                "type": [
                                    "string",
                                    "null"
                                ],
                                "description": "One of the workspace's SMS senders that the key's issuer may send as: an approved sender ID by name (a `value` from GET /api/v3/sms/senders), one of its SMS numbers or short codes, or a sender key (\"sms:sender-id:12\"). Saved as its key; a sender that is not approved, or not this workspace's, is refused (422 on sms.sender), and so is a campaign that sends an SMS when the workspace has no sender at all.",
                                "example": "MOMO NET"
                            }
                        }
                    },
                    "ivr_flow_id": {
                        "type": "integer",
                        "description": "ivr mode: a published IVR flow."
                    },
                    "agent_config_id": {
                        "type": "string",
                        "description": "ai mode: the AI agent."
                    },
                    "ai_instructions": {
                        "type": "string",
                        "description": "ai mode: why we are calling, for the agent (\u2264 4000)."
                    },
                    "answer_fields": {
                        "type": "array",
                        "description": "ai mode: what to find out on each call (\u2264 10).",
                        "items": {
                            "type": "object",
                            "description": "One answer.",
                            "properties": {
                                "key": {
                                    "type": "string",
                                    "description": "lower_snake key."
                                },
                                "label": {
                                    "type": "string",
                                    "description": "What it is called."
                                },
                                "type": {
                                    "type": "string",
                                    "description": "text, number, date, boolean or choice."
                                }
                            }
                        }
                    },
                    "when": {
                        "type": "object",
                        "description": "When to start. Left out: now.",
                        "properties": {
                            "start": {
                                "type": "string",
                                "description": "now, at (with `at`) or draft.",
                                "enum": [
                                    "now",
                                    "at",
                                    "draft"
                                ]
                            },
                            "at": {
                                "type": "string",
                                "description": "ISO 8601 with its UTC offset."
                            },
                            "timezone": {
                                "type": "string",
                                "description": "IANA timezone the time is in."
                            }
                        }
                    },
                    "advanced": {
                        "type": "object",
                        "description": "Everything else; left out takes the goal's defaults.",
                        "properties": {
                            "calling_window": {
                                "type": "object",
                                "description": "When calls may go out. Left out: Monday\u2013Saturday 08:00\u201320:00 in the workspace's timezone.",
                                "properties": {
                                    "timezone": {
                                        "type": "string",
                                        "description": "IANA timezone.",
                                        "example": "Africa/Dar_es_Salaam"
                                    },
                                    "days": {
                                        "type": "array",
                                        "description": "ISO weekdays allowed (1 = Monday \u2026 7 = Sunday).",
                                        "items": {
                                            "type": "integer",
                                            "description": "An ISO weekday."
                                        }
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Opening time, HH:MM."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Closing time, HH:MM (after `from`)."
                                    }
                                }
                            },
                            "max_tries": {
                                "type": "integer",
                                "description": "Tries per person (1-6, default 3)."
                            },
                            "retry_policy": {
                                "type": "object",
                                "description": "Retry steps per result: {\"no_answer\": [120, \"next_day_other_half\"], \"busy\": [15, 60]} (minutes or next_day / next_day_other_half).",
                                "additionalProperties": true
                            },
                            "ring_seconds": {
                                "type": "integer",
                                "description": "How long each call rings (15-60, default 30)."
                            },
                            "lines": {
                                "type": "integer",
                                "description": "At most this many calls at once (1-16; default the package's lines)."
                            },
                            "from_number": {
                                "type": "string",
                                "description": "Older clients: the same as the top-level from_number, which wins when both are sent.",
                                "deprecated": true
                            },
                            "stop_rule": {
                                "type": "string",
                                "description": "call_everyone (default) or stop_on_answer."
                            },
                            "voicemail_action": {
                                "type": "string",
                                "description": "hang_up (default) or leave_message."
                            },
                            "max_call_seconds": {
                                "type": "integer",
                                "description": "The longest a call may last (30-1800; default by mode: message 90, ivr 180, ai 240)."
                            },
                            "record_calls": {
                                "type": "boolean",
                                "description": "Record the calls (default: AI calls only)."
                            },
                            "cooldown_hours": {
                                "type": "integer",
                                "description": "Skip people another campaign called within this many hours (0-168, default 24; 0 for order confirmations)."
                            },
                            "fallback_sms": {
                                "type": "object",
                                "description": "SMS the people not reached when it finishes, from the campaign's sms.sender.",
                                "properties": {
                                    "auto": {
                                        "type": "boolean",
                                        "description": "Send it automatically."
                                    },
                                    "sender_id": {
                                        "type": "string",
                                        "description": "Older clients: the same as sms.sender, which wins when both are sent.",
                                        "deprecated": true
                                    },
                                    "text": {
                                        "type": "string",
                                        "description": "The SMS (\u2264 459)."
                                    }
                                }
                            },
                            "repeat_rule": {
                                "type": "string",
                                "description": "never, daily or weekly."
                            },
                            "external_ref": {
                                "type": "string",
                                "description": "Your own reference (\u2264 191): a create with one already used returns that campaign instead of a new one."
                            },
                            "budget_cap": {
                                "type": "number",
                                "description": "Pause when the campaign has spent this much."
                            },
                            "is_rolling": {
                                "type": "boolean",
                                "description": "Always-on: the campaign stays open; add people with POST \u2026/targets/batch or an Automation (\"order received\"). It may open with nobody yet."
                            }
                        }
                    },
                    "connections": {
                        "type": "object",
                        "description": "What results do in other modules. Moving leads needs leads.edit; writing Daftari rows needs data.records.edit and write access to the table.",
                        "properties": {
                            "daftari": {
                                "type": "object",
                                "description": "Write answers back to the Daftari rows the people came from.",
                                "properties": {
                                    "table": {
                                        "type": "string",
                                        "description": "The table (default: the audience's)."
                                    },
                                    "answers": {
                                        "type": "object",
                                        "description": "answer key \u2192 column key.",
                                        "additionalProperties": {
                                            "type": "string",
                                            "description": "A column key."
                                        }
                                    },
                                    "result_column": {
                                        "type": "string",
                                        "description": "A column for the person's result."
                                    },
                                    "summary_column": {
                                        "type": "string",
                                        "description": "A column for the AI's summary."
                                    }
                                }
                            },
                            "leads": {
                                "type": "object",
                                "description": "Move an interested person's open lead.",
                                "properties": {
                                    "answer_key": {
                                        "type": "string",
                                        "description": "The answer that means \"interested\" (default interested)."
                                    },
                                    "stage": {
                                        "type": "string",
                                        "description": "The stage to move the lead to (not lost / unqualified)."
                                    },
                                    "note": {
                                        "type": "boolean",
                                        "description": "Add a note with the result (default true)."
                                    }
                                }
                            }
                        }
                    },
                    "consent": {
                        "type": "boolean",
                        "description": "These are your customers and they agreed to hear from you. Required to start; recorded with who and when."
                    },
                    "action": {
                        "type": "string",
                        "description": "start_now, schedule or draft \u2014 wins over when.start.",
                        "enum": [
                            "start_now",
                            "schedule",
                            "draft"
                        ]
                    }
                }
            },
            "CallCampaignEstimate": {
                "type": "object",
                "description": "What a campaign will likely cost, the most it can cost, and when it finishes \u2014 from the workspace's real prices.",
                "properties": {
                    "people": {
                        "type": "integer",
                        "description": "People who will really be called."
                    },
                    "mode": {
                        "type": "string",
                        "description": "message, ai or ivr."
                    },
                    "currency": {
                        "type": "string",
                        "description": "Currency of every amount."
                    },
                    "minutes": {
                        "type": "number",
                        "description": "Likely minutes talked."
                    },
                    "minutes_likely": {
                        "type": "number",
                        "description": "Likely minutes talked."
                    },
                    "minutes_max": {
                        "type": "number",
                        "description": "Minutes if everyone talks to the limit."
                    },
                    "likely_cost": {
                        "type": "number",
                        "description": "Likely cost (about 60% answer, typical length)."
                    },
                    "max_cost": {
                        "type": "number",
                        "description": "The most it can cost: everyone answers on the first try and talks to the limit."
                    },
                    "hold_amount": {
                        "type": "number",
                        "description": "What is held from the wallet while it runs (max_cost, capped by the budget)."
                    },
                    "per_person_reached": {
                        "type": "number",
                        "description": "Cost of one typical answered call."
                    },
                    "per_call_max": {
                        "type": "number",
                        "description": "Cost of one call at its longest."
                    },
                    "lines": {
                        "type": "integer",
                        "description": "Calls at once."
                    },
                    "starts_at": {
                        "type": "string",
                        "description": "When calling starts (inside calling hours)."
                    },
                    "finishes_at": {
                        "type": "string",
                        "description": "When the first round should finish."
                    },
                    "duration_minutes": {
                        "type": "integer",
                        "description": "Calling time on these lines."
                    },
                    "calling_window": {
                        "type": "object",
                        "description": "The calling hours used.",
                        "properties": {
                            "timezone": {
                                "type": "string",
                                "description": "IANA timezone."
                            },
                            "days": {
                                "type": "array",
                                "description": "ISO weekdays.",
                                "items": {
                                    "type": "integer",
                                    "description": "An ISO weekday."
                                }
                            },
                            "from": {
                                "type": "string",
                                "description": "Opening time."
                            },
                            "to": {
                                "type": "string",
                                "description": "Closing time."
                            },
                            "enforced": {
                                "type": "boolean",
                                "description": "Whether the hours are enforced."
                            }
                        }
                    },
                    "calling_window_label": {
                        "type": "string",
                        "description": "The calling hours in words."
                    },
                    "wallet": {
                        "type": "object",
                        "description": "The wallet.",
                        "properties": {
                            "available": {
                                "type": "number",
                                "description": "What the campaign may spend (spendable balance, its own hold, package minutes)."
                            },
                            "postpaid": {
                                "type": "boolean",
                                "description": "A postpaid workspace is never short."
                            },
                            "held": {
                                "type": "number",
                                "description": "This campaign's hold."
                            },
                            "balance": {
                                "type": "number",
                                "description": "The wallet balance."
                            },
                            "currency": {
                                "type": "string",
                                "description": "The wallet currency."
                            }
                        }
                    },
                    "wallet_available": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "The same as wallet.available; null when postpaid."
                    },
                    "enough": {
                        "type": "boolean",
                        "description": "The wallet covers the most it can cost."
                    },
                    "enough_for_likely": {
                        "type": "boolean",
                        "description": "The wallet covers the likely cost."
                    },
                    "shortfall": {
                        "type": "number",
                        "description": "What is missing for the most it can cost."
                    },
                    "short_by": {
                        "type": "number",
                        "description": "The same as shortfall."
                    },
                    "budget_cap": {
                        "type": [
                            "number",
                            "null"
                        ],
                        "description": "The budget cap."
                    },
                    "assumptions": {
                        "type": "object",
                        "description": "What the estimate assumed.",
                        "properties": {
                            "answer_rate": {
                                "type": "number",
                                "description": "Share of people who answer."
                            },
                            "talk_seconds": {
                                "type": "integer",
                                "description": "Typical talk time."
                            },
                            "max_call_seconds": {
                                "type": "integer",
                                "description": "Longest call."
                            },
                            "ring_seconds": {
                                "type": "integer",
                                "description": "Ring time."
                            }
                        }
                    },
                    "rates": {
                        "type": "object",
                        "description": "The prices used.",
                        "properties": {
                            "per_minute": {
                                "type": "number",
                                "description": "Outbound price per minute."
                            },
                            "connect_fee": {
                                "type": "number",
                                "description": "Fee per connected call."
                            },
                            "increment_seconds": {
                                "type": "integer",
                                "description": "Billing step."
                            },
                            "ai_per_minute": {
                                "type": "number",
                                "description": "AI cost per minute (ai mode)."
                            }
                        }
                    },
                    "audience": {
                        "type": [
                            "object",
                            "null"
                        ],
                        "description": "The cleaning report, when an audience was sent: total, kept, duplicates, invalid (by row), opted_out, cooldown.",
                        "additionalProperties": true
                    }
                }
            },
            "CallRefusalEnvelope": {
                "type": "object",
                "description": "A refusal of the calls / call-campaigns rules (not a validation failure): the error envelope plus a stable `code` and, where there are facts, `details`.",
                "properties": {
                    "status": {
                        "type": "string",
                        "description": "Always \"error\".",
                        "enum": [
                            "error"
                        ]
                    },
                    "message": {
                        "type": "string",
                        "description": "Human-readable reason."
                    },
                    "code": {
                        "type": "string",
                        "description": "What to branch on. insufficient_balance (402) \u2014 details.required, available, short_by, currency and, for campaigns, the whole `estimate`; invalid_state (409) \u2014 details.status; consent_required; opted_out \u2014 the person is on the do-not-call list; outside_calling_hours \u2014 details.next_opening; invalid_number / country_not_allowed / no_caller_number / unknown_caller_number; rate_limited (429, Retry-After) \u2014 this number had the most calls allowed in the window; no_free_line / trunk_busy / agent_capacity (429, Retry-After); pbx_unreachable / provider_failure / trunk_unavailable (503/502, retry with the same Idempotency-Key); pbx_refused \u2014 details.pbx_error; idempotency_conflict; not_provisioned; forbidden (403) \u2014 the key's issuer lacks a right the campaign needs (details.permission: leads.view for lead stages, data.view for a Daftari audience, leads.edit / data.records.edit for connections), or access to that Daftari table."
                    },
                    "details": {
                        "type": "object",
                        "description": "Code-specific facts, present only when there are any.",
                        "additionalProperties": true
                    }
                },
                "required": [
                    "status",
                    "message",
                    "code"
                ]
            },
            "JsonRpcRequest": {
                "type": "object",
                "title": "JSON-RPC 2.0 request",
                "description": "The body of every MCP call. The **operation is `method`**, not the URL: one server answers `initialize`, `tools/list`, `tools/call`, `ping` and the notification methods on the same path.\n\nA notification (a request with no `id`) is answered with `202 Accepted` and an empty body.",
                "required": [
                    "jsonrpc",
                    "method"
                ],
                "properties": {
                    "jsonrpc": {
                        "type": "string",
                        "const": "2.0",
                        "description": "Always the string \"2.0\"."
                    },
                    "id": {
                        "type": [
                            "string",
                            "integer"
                        ],
                        "description": "Correlates the response with this request. Omit it to send a notification, which is acknowledged rather than answered."
                    },
                    "method": {
                        "type": "string",
                        "description": "The JSON-RPC method. `initialize` opens the session, `tools/list` returns what this server offers, `tools/call` runs one.",
                        "examples": [
                            "initialize",
                            "tools/list",
                            "tools/call",
                            "ping"
                        ]
                    },
                    "params": {
                        "type": "object",
                        "description": "Method arguments. For `tools/call` this is `{\"name\": \"<tool>\", \"arguments\": { \u2026 }}`, where `arguments` must satisfy that tool's `inputSchema`.",
                        "additionalProperties": true
                    }
                },
                "x-generated-by": "php artisan mcp:manifest"
            },
            "JsonRpcResponse": {
                "type": "object",
                "title": "JSON-RPC 2.0 response",
                "description": "Exactly one of `result` or `error` is present.\n\nMind the two layers: a tool that fails *cleanly* answers `200` with a `result` whose `isError` is true \u2014 the model is meant to read the message and try something else. `error` means the call never reached a tool.",
                "required": [
                    "jsonrpc"
                ],
                "properties": {
                    "jsonrpc": {
                        "type": "string",
                        "const": "2.0",
                        "description": "Always the string \"2.0\"."
                    },
                    "id": {
                        "type": [
                            "string",
                            "integer",
                            "null"
                        ],
                        "description": "The `id` of the request being answered; null when the request could not be parsed."
                    },
                    "result": {
                        "type": "object",
                        "description": "The method result. Shape depends on `method` \u2014 see the examples.",
                        "additionalProperties": true
                    },
                    "error": {
                        "$ref": "#/components/schemas/JsonRpcError",
                        "description": "Present instead of `result` when the call was refused before any tool ran."
                    }
                },
                "x-generated-by": "php artisan mcp:manifest"
            },
            "JsonRpcError": {
                "type": "object",
                "title": "JSON-RPC 2.0 error",
                "description": "A protocol-level failure: the request was refused before any tool ran. Refusals from this platform carry `data.reason`, which names the decision \u2014 `missing_token`, `server_not_granted`, `module_disabled` \u2014 so a client can tell \"reconnect with more access\" apart from \"log in again\".",
                "required": [
                    "code",
                    "message"
                ],
                "properties": {
                    "code": {
                        "type": "integer",
                        "description": "JSON-RPC error code. `-32700` parse error, `-32600` invalid request, `-32601` unknown method, `-32602` invalid params, `-32001` unauthenticated, `-32002` refused."
                    },
                    "message": {
                        "type": "string",
                        "description": "A sentence written for a person, not a code."
                    },
                    "data": {
                        "type": "object",
                        "description": "Extra detail. `reason` names the specific decision behind a refusal.",
                        "properties": {
                            "reason": {
                                "type": "string",
                                "description": "The specific decision \u2014 `missing_token`, `server_not_granted`, `module_disabled`, `surface_disabled`."
                            }
                        },
                        "additionalProperties": true
                    }
                },
                "x-generated-by": "php artisan mcp:manifest"
            },
            "ToolDefinition": {
                "type": "object",
                "title": "Tool definition",
                "description": "One entry of a `tools/list` result. `inputSchema` is a complete JSON Schema for the tool's arguments \u2014 it is the whole argument contract, which is why tools are not modelled as REST operations here.\n\nThe same definitions, for every server at once and without a credential, are at `GET /api-docs/mcp.json`.",
                "required": [
                    "name",
                    "inputSchema"
                ],
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "The value to send as `params.name` on `tools/call`.",
                        "examples": [
                            "list_ivr_flows"
                        ]
                    },
                    "title": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "A human label, when the tool sets one."
                    },
                    "description": {
                        "type": "string",
                        "description": "What the tool does and when to reach for it. This is the text a model actually chooses on."
                    },
                    "inputSchema": {
                        "type": "object",
                        "description": "JSON Schema (draft 2020-12) for `params.arguments`.",
                        "additionalProperties": true
                    },
                    "outputSchema": {
                        "type": "object",
                        "description": "Present only when the tool declares a structured result.",
                        "additionalProperties": true
                    },
                    "annotations": {
                        "type": "object",
                        "description": "Behavioural hints describe the complete call, including indirect effects. Our calls queue a persistent audit entry, so `readOnlyHint` is false even for retrievals; primary read/write permissions and controls are separate. `destructiveHint` includes deletion, overwrites, spending and irreversible deliveries. `openWorldHint` includes external providers and configured webhook recipients.\n\nTwo more are ours. `version` is a hash of this tool's contract \u2014 its name, description and argument schema \u2014 so a cached definition can be checked rather than trusted. `available` says whether THIS connection could actually call it; when it is false, `withheld_capability` names the tick or permission that is missing and `withheld_reason` is the sentence a call would come back with. The aggregate root at `/mcp` leaves a tool it cannot offer out of the list entirely and explains it on the call; the per-area URLs list their tools whatever the credential holds, so that is where an unavailable one shows up.",
                        "properties": {
                            "readOnlyHint": {
                                "type": "boolean",
                                "description": "False for audited calls, including primary retrievals, because the audit entry is persisted."
                            },
                            "destructiveHint": {
                                "type": "boolean",
                                "description": "True for a supported deletion, overwrite, spending or irreversible delivery mode, including indirect effects."
                            },
                            "idempotentHint": {
                                "type": "boolean",
                                "description": "True when calling twice with the same arguments is the same as calling once."
                            },
                            "openWorldHint": {
                                "type": "boolean",
                                "description": "True when a supported mode reaches external providers, public resources or open-ended recipients rather than only bounded private account data."
                            },
                            "version": {
                                "type": "string",
                                "description": "Eight hex characters over the tool's name, description and argument schema. It changes when the contract changes, and never otherwise.",
                                "examples": [
                                    "3f9c1a04"
                                ]
                            },
                            "available": {
                                "type": "boolean",
                                "description": "False when this connection was not granted what the tool needs. It is still listed, and calling it returns the reason rather than \"not found\"."
                            },
                            "withheld_capability": {
                                "type": "string",
                                "description": "Present when `available` is false: the consent-screen tick or the permission that is missing, worded as the refusal words it.",
                                "examples": [
                                    "Change tables and fields"
                                ]
                            },
                            "withheld_reason": {
                                "type": "string",
                                "description": "Present when `available` is false: what a call would come back with, in a sentence."
                            }
                        },
                        "additionalProperties": true
                    }
                },
                "x-generated-by": "php artisan mcp:manifest"
            },
            "ServerInfo": {
                "type": "object",
                "title": "MCP server",
                "description": "One server as `GET /mcp/v1` reports it for the calling credential. `available` is per-credential: a capability the account holder did not grant leaves the server unreachable, not merely unauthorized.",
                "required": [
                    "key",
                    "name",
                    "url",
                    "available"
                ],
                "properties": {
                    "key": {
                        "type": "string",
                        "description": "The `{server}` path segment.",
                        "enum": [
                            "ivr",
                            "flows",
                            "forms",
                            "data",
                            "approvals",
                            "payments",
                            "automations",
                            "alerts",
                            "operations",
                            "studio",
                            "numbers",
                            "groups",
                            "agents",
                            "orders",
                            "shop",
                            "tickets",
                            "kb",
                            "content",
                            "calls",
                            "routing",
                            "meetings",
                            "messaging",
                            "inbox",
                            "comments",
                            "posts",
                            "contacts",
                            "leads",
                            "overview",
                            "accounts",
                            "navigate",
                            "account"
                        ]
                    },
                    "name": {
                        "type": "string",
                        "description": "Display name."
                    },
                    "description": {
                        "type": "string",
                        "description": "What the server is for."
                    },
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "The absolute endpoint to point a client at."
                    },
                    "available": {
                        "type": "boolean",
                        "description": "Whether this credential may reach it."
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "description": "Why not, when `available` is false."
                    }
                },
                "x-generated-by": "php artisan mcp:manifest"
            }
        },
        "parameters": {
            "Limit": {
                "name": "limit",
                "in": "query",
                "required": false,
                "description": "Rows per page, 1\u2013100. Defaults to 20 (25 for catalogue endpoints). Values above 100 are clamped.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 20
                },
                "example": 20
            },
            "PerPage": {
                "name": "per_page",
                "in": "query",
                "required": false,
                "description": "Alias of `limit`, for clients that already speak Laravel pagination. `limit` wins if both are sent.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100
                },
                "example": 25
            },
            "Page": {
                "name": "page",
                "in": "query",
                "required": false,
                "description": "Page number, 1-based. Read `data.pagination.has_more_pages` to know when to stop.",
                "schema": {
                    "type": "integer",
                    "minimum": 1,
                    "default": 1
                },
                "example": 1
            },
            "MessageStatus": {
                "name": "status",
                "in": "query",
                "required": false,
                "description": "Only messages in this delivery state.",
                "schema": {
                    "type": "string",
                    "enum": [
                        "queued",
                        "processing",
                        "sent",
                        "checking_delivery",
                        "delivered",
                        "read",
                        "failed",
                        "received"
                    ]
                },
                "example": "delivered"
            },
            "MessageDirection": {
                "name": "direction",
                "in": "query",
                "required": false,
                "description": "Only messages you sent (`outbound`) or received (`inbound`).",
                "schema": {
                    "type": "string",
                    "enum": [
                        "inbound",
                        "outbound"
                    ]
                },
                "example": "outbound"
            },
            "MessageUid": {
                "name": "uid",
                "in": "path",
                "required": true,
                "description": "The message `uid` returned by the send call (or its numeric `id`).",
                "schema": {
                    "type": "string"
                },
                "example": "msg_kuutop7qhc076g316z4k"
            },
            "CampaignUid": {
                "name": "uid",
                "in": "path",
                "required": true,
                "description": "The campaign `uid` returned when the campaign was created (or its numeric `id`).",
                "schema": {
                    "type": "string"
                },
                "example": "cmp_w5aqybtpzqj79ngzqcoh"
            },
            "GroupId": {
                "name": "id",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "integer"
                },
                "description": "The platform id of the group (from the list).",
                "example": 12
            },
            "ContactUid": {
                "name": "uid",
                "in": "path",
                "required": true,
                "description": "The contact `uid` returned when it was created (or its numeric `id`).",
                "schema": {
                    "type": "string"
                },
                "example": "ctc_gz0os4at1itzvvpxvewj"
            },
            "ContactSearch": {
                "name": "search",
                "in": "query",
                "required": false,
                "description": "Match contacts whose name or phone number contains this text.",
                "schema": {
                    "type": "string"
                },
                "example": "Asha"
            },
            "CatalogueId": {
                "name": "catalogue",
                "in": "path",
                "required": true,
                "description": "Catalogue (shop) id, as returned by `GET /api/v3/catalogues`.",
                "schema": {
                    "type": "integer"
                },
                "example": 1
            },
            "ProductId": {
                "name": "product",
                "in": "path",
                "required": true,
                "description": "Product id. Not the `retailer_id` \u2014 that is your own SKU.",
                "schema": {
                    "type": "integer"
                },
                "example": 1
            },
            "OrderId": {
                "name": "order",
                "in": "path",
                "required": true,
                "description": "Order id, as returned by `GET /api/v3/catalogues/orders`.",
                "schema": {
                    "type": "integer"
                },
                "example": 1
            },
            "ProductSearch": {
                "name": "search",
                "in": "query",
                "required": false,
                "description": "Match products whose name or `retailer_id` contains this text.",
                "schema": {
                    "type": "string"
                },
                "example": "kanga"
            },
            "ProductAvailability": {
                "name": "availability",
                "in": "query",
                "required": false,
                "description": "Only products in this stock state.",
                "schema": {
                    "type": "string",
                    "enum": [
                        "in stock",
                        "out of stock",
                        "preorder",
                        "available for order",
                        "discontinued"
                    ]
                },
                "example": "in stock"
            },
            "OrderStatusFilter": {
                "name": "status",
                "in": "query",
                "required": false,
                "description": "Only orders in this fulfilment state.",
                "schema": {
                    "type": "string",
                    "enum": [
                        "pending",
                        "confirmed",
                        "processing",
                        "shipped",
                        "delivered",
                        "cancelled",
                        "refunded"
                    ]
                },
                "example": "pending"
            },
            "DataTableId": {
                "name": "table",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "format": "uuid"
                },
                "description": "The table id (from `GET /api/v3/data/tables`). Anything that is not a UUID, or a table belonging to another tenant, answers 404.",
                "example": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b"
            },
            "DataRecordId": {
                "name": "record",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "format": "uuid"
                },
                "description": "The record id (from a records page, or the `record.id` returned when it was created).",
                "example": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d"
            },
            "DataGroupId": {
                "name": "group",
                "in": "path",
                "required": true,
                "schema": {
                    "type": "string",
                    "format": "uuid"
                },
                "description": "The group id (from `GET /api/v3/data/groups`). Anything that is not a UUID, or a group belonging to another tenant, answers 404.",
                "example": "7c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f"
            }
        },
        "responses": {
            "Unauthorized": {
                "description": "Missing, unknown or expired bearer token.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                        },
                        "example": {
                            "status": "error",
                            "message": "Invalid API token."
                        }
                    }
                }
            },
            "Forbidden": {
                "description": "The record exists but belongs to another tenant.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                        },
                        "example": {
                            "status": "error",
                            "message": "This catalogue belongs to another tenant."
                        }
                    }
                }
            },
            "NotFound": {
                "description": "No such record for this tenant.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                        },
                        "example": {
                            "status": "error",
                            "message": "Resource not found."
                        }
                    }
                }
            },
            "ValidationFailed": {
                "description": "The payload failed validation. `errors` maps each rejected field to its messages.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                        },
                        "example": {
                            "status": "error",
                            "message": "Validation failed.",
                            "errors": {
                                "recipient": [
                                    "Provide recipient or recipients."
                                ]
                            }
                        }
                    }
                }
            },
            "RateLimited": {
                "description": "More than 120 requests in a minute on this token. Wait for `Retry-After` seconds and retry.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds to wait before retrying.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 42
                    },
                    "X-RateLimit-Limit": {
                        "description": "Requests allowed per minute.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 120
                    },
                    "X-RateLimit-Remaining": {
                        "description": "Requests left in the current window.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 0
                    },
                    "X-RateLimit-Reset": {
                        "description": "Unix timestamp when the window resets.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 1789012345
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/RateLimitError"
                        },
                        "example": {
                            "status": "error",
                            "message": "Too many requests. Retry after the number of seconds in the Retry-After header."
                        }
                    }
                }
            },
            "UpstreamFailure": {
                "description": "WhatsApp/Meta refused the call. The message repeats what they said; the record was not changed.",
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                        },
                        "example": {
                            "status": "error",
                            "message": "(#100) Invalid parameter: product image_url is not reachable."
                        }
                    }
                }
            }
        }
    },
    "paths": {
        "/api/v3/sms/send": {
            "post": {
                "tags": [
                    "SMS"
                ],
                "operationId": "v3SmsSend",
                "summary": "Send an SMS",
                "description": "Creates one record per normalized recipient and normally attempts provider delivery synchronously, sequentially. HTTP 201 can contain sent or failed records; inspect every status/error_message. Future schedules, admission deferral or fallback can return queued. Repeating this POST is not protected by a request Idempotency-Key. Use a nonempty message. SMS types plain/text/sms are supported; other types require media_url and provider media support.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "recipient": {
                                        "type": "string",
                                        "description": "Recipients separated by commas, semicolons or whitespace. Combined with recipients and deduplicated by exact string.",
                                        "maxLength": 4000
                                    },
                                    "recipients": {
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "maxLength": 191
                                        },
                                        "description": "Additional recipient strings; entries also split on commas, semicolons and whitespace. Can be used together with recipient."
                                    },
                                    "sender_id": {
                                        "type": "string",
                                        "description": "Optional approved sender ID, tenant-owned SMS-capable number, or active short code. Unknown or ambiguous identities are rejected. `GET /api/v3/sms/senders` lists every usable identity, with `value` being what to pass here.",
                                        "maxLength": 64
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "Message type (e.g. plain).",
                                        "maxLength": 60
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Message text, maximum 4096 characters. Supply meaningful nonempty text; the current controller substitutes a generic body if absent.",
                                        "maxLength": 4096
                                    },
                                    "schedule_time": {
                                        "type": "string",
                                        "description": "Optional ISO datetime for scheduled send.",
                                        "maxLength": 100
                                    },
                                    "body": {
                                        "type": "string",
                                        "maxLength": 4096,
                                        "description": "Alias of `message`, for clients that already speak that field. `message` wins if both are sent."
                                    },
                                    "message_type": {
                                        "type": "string",
                                        "description": "Takes precedence over type. Defaults to plain for SMS and text for WhatsApp; supplied payload objects determine provider send behavior.",
                                        "maxLength": 60
                                    },
                                    "media_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Publicly reachable media to attach. Turns the send into an MMS-style message on gateways that support one."
                                    },
                                    "media_type": {
                                        "type": "string",
                                        "maxLength": 32,
                                        "description": "Media kind (image, video, document\u2026). Defaults to the message type."
                                    }
                                },
                                "anyOf": [
                                    {
                                        "required": [
                                            "recipient"
                                        ]
                                    },
                                    {
                                        "required": [
                                            "recipients"
                                        ]
                                    }
                                ],
                                "description": "Supply recipient and/or recipients. Inputs are merged and exact duplicates removed. Message/body and payload combinations follow this endpoint description."
                            },
                            "examples": {
                                "default": {
                                    "summary": "Single recipient (most common)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "sender_id": "MyBrand",
                                        "message": "Hello from Momo Business \u2014 your verification code is 4821."
                                    }
                                },
                                "multi_recipient_csv": {
                                    "summary": "Multiple recipients (comma-separated)",
                                    "value": {
                                        "recipient": "255700111222,255700111223,255700111224",
                                        "sender_id": "MyBrand",
                                        "message": "Branch closed early today \u2014 back tomorrow at 8am."
                                    }
                                },
                                "multi_recipient_array": {
                                    "summary": "Multiple recipients (array form)",
                                    "value": {
                                        "recipients": [
                                            "255700111222",
                                            "255700111223",
                                            "255700111224"
                                        ],
                                        "sender_id": "MyBrand",
                                        "message": "Reminder: payment due tomorrow."
                                    }
                                },
                                "scheduled": {
                                    "summary": "Scheduled send (queue for later)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "sender_id": "MyBrand",
                                        "message": "Good morning! Your appointment is at 10am.",
                                        "schedule_time": "2030-10-12T09:00:00+03:00"
                                    }
                                },
                                "long_unicode": {
                                    "summary": "Long Unicode message (will be split into multiple SMS segments)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "sender_id": "MyBrand",
                                        "message": "Mteja mpendwa, asante kwa kutembelea duka letu. Tunakushukuru kwa upendeleo wako wa kuendelea kununua bidhaa zetu. Tafadhali piga 0700123456 kwa msaada zaidi."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "One message record per recipient. `data.messages[].status` is the delivery state at the moment we answered; watch the `message.*` webhooks for what happens after.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "messages"
                                            ],
                                            "properties": {
                                                "messages": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Message",
                                                        "description": "The message record."
                                                    },
                                                    "description": "One record per recipient, in the order they were given."
                                                }
                                            },
                                            "description": "The messages this call created."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "messages": [
                                                    {
                                                        "id": 101,
                                                        "uid": "msg_01JXYZSMS01",
                                                        "direction": "outbound",
                                                        "channel_type": "sms",
                                                        "sender": "MyBrand",
                                                        "recipient": "255700111222",
                                                        "body": "Hello from API v3",
                                                        "status": "sent"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Invalid API token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "At least one recipient is required.",
                                            "errors": {
                                                "recipient": [
                                                    "Provide recipient or recipients."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/sms/campaign": {
            "post": {
                "tags": [
                    "SMS"
                ],
                "operationId": "v3SmsCampaignCreate",
                "summary": "Create an SMS campaign",
                "description": "Creates one one-time SMS campaign per resolved contact group. Numeric IDs and group UUIDs may be separated by whitespace, comma or semicolon. Unknown groups are skipped when at least one resolves; no resolved groups returns 404. Campaign completed means recipient jobs were dispatched, not all messages delivered. Current dispatch skips blacklisted/missing phone numbers but does not filter is_subscribed. No recurrence or request-key idempotency is exposed here.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "contact_list_id": {
                                        "type": "string",
                                        "description": "Contact group to send to \u2014 the numeric id or the group UUID. Comma-separate several, and each one becomes its own campaign.",
                                        "maxLength": 2000
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "The message body. `{name}` and any custom field on the contact are substituted per recipient.",
                                        "maxLength": 4096
                                    },
                                    "sender_id": {
                                        "type": "string",
                                        "description": "Optional approved sender ID, tenant-owned SMS-capable number, or active short code. `GET /api/v3/sms/senders` lists every usable identity, with `value` being what to pass here.",
                                        "maxLength": 64
                                    },
                                    "schedule_time": {
                                        "type": "string",
                                        "description": "ISO 8601 datetime to start the campaign. Omit it and the campaign starts immediately.",
                                        "maxLength": 100
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "A name for the campaign in the dashboard. Defaults to \"API Campaign - <group name>\".",
                                        "maxLength": 160
                                    }
                                },
                                "required": [
                                    "contact_list_id",
                                    "message"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "contact_list_id": "grp_01JXYZABC",
                                        "message": "Campaign message",
                                        "sender_id": "Brand"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Campaigns created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "campaigns"
                                            ],
                                            "properties": {
                                                "campaigns": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Campaign",
                                                        "description": "The campaign record."
                                                    },
                                                    "description": "One campaign per contact group in `contact_list_id`."
                                                }
                                            },
                                            "description": "The campaigns this call created."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "campaigns": [
                                                    {
                                                        "id": 15,
                                                        "uid": "cmp_01JXYZ001",
                                                        "name": "API Campaign - VIP List",
                                                        "status": "draft",
                                                        "channel_type": "sms",
                                                        "message": "Campaign message"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Invalid API token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "Validation error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "contact_list_id must contain at least one group id."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/sms": {
            "get": {
                "tags": [
                    "SMS"
                ],
                "operationId": "v3SmsList",
                "summary": "List SMS messages",
                "description": "Returns tenant-scoped SMS message logs with pagination.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/MessageStatus"
                    },
                    {
                        "$ref": "#/components/parameters/MessageDirection"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "SMS collection.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items",
                                                "pagination"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Message",
                                                        "description": "The message record."
                                                    },
                                                    "description": "The messages on this page, newest first."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state for this list: where you are and whether more pages follow."
                                                }
                                            },
                                            "description": "A page of messages and its page state."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "items": [
                                                    {
                                                        "id": 101,
                                                        "uid": "msg_01JXYZSMS01",
                                                        "direction": "outbound",
                                                        "channel_type": "sms",
                                                        "recipient": "255700111222",
                                                        "body": "Hello from API v3",
                                                        "status": "queued"
                                                    }
                                                ],
                                                "pagination": {
                                                    "current_page": 1,
                                                    "per_page": 20,
                                                    "last_page": 1,
                                                    "total": 1,
                                                    "has_more_pages": false
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Missing bearer token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/sms/{uid}": {
            "get": {
                "tags": [
                    "SMS"
                ],
                "operationId": "v3SmsShow",
                "summary": "Get an SMS message",
                "description": "Fetches one SMS message by public uid with numeric id fallback.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/MessageUid"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Single SMS message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Message",
                                            "description": "The message record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 101,
                                                "uid": "msg_01JXYZSMS01",
                                                "direction": "outbound",
                                                "channel_type": "sms",
                                                "recipient": "255700111222",
                                                "body": "Hello from API v3",
                                                "status": "delivered"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Message not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Message not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/campaign/{uid}/view": {
            "get": {
                "tags": [
                    "SMS"
                ],
                "operationId": "v3CampaignShow",
                "summary": "View one campaign",
                "description": "Retrieves one SMS campaign by uid.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CampaignUid"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Campaign details.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Campaign",
                                            "description": "The campaign record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 15,
                                                "uid": "cmp_01JXYZ001",
                                                "name": "API Campaign - VIP List",
                                                "status": "running",
                                                "channel_type": "sms",
                                                "message": "Campaign message"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Campaign not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Campaign not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/send": {
            "post": {
                "tags": [
                    "WhatsApp"
                ],
                "operationId": "v3WhatsAppSend",
                "summary": "Send a WhatsApp message",
                "description": "Creates one record per normalized recipient and normally attempts provider delivery synchronously, sequentially. HTTP 201 can contain sent or failed records; inspect every status/error_message. Future schedules, admission deferral or fallback can return queued. Repeating this POST is not protected by a request Idempotency-Key. Supports text, templates, media, interactive payloads and reactions. Provider validation, including conversation-window rules, can appear as a failed message in a 201 response.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "recipient": {
                                        "type": "string",
                                        "description": "Recipients separated by commas, semicolons or whitespace. Combined with recipients and deduplicated by exact string.",
                                        "maxLength": 4000
                                    },
                                    "recipients": {
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "maxLength": 191
                                        },
                                        "description": "Additional recipient strings; entries also split on commas, semicolons and whitespace. Can be used together with recipient."
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "Text or local preview text, maximum 4096 characters. With a template, this does not replace the approved provider template body.",
                                        "maxLength": 4096
                                    },
                                    "body": {
                                        "type": "string",
                                        "description": "Alias of `message`. `message` wins if both are sent.",
                                        "maxLength": 4096
                                    },
                                    "message_type": {
                                        "type": "string",
                                        "description": "Takes precedence over type. Defaults to plain for SMS and text for WhatsApp; supplied payload objects determine provider send behavior.",
                                        "maxLength": 60
                                    },
                                    "type": {
                                        "type": "string",
                                        "description": "Alias of `message_type`.",
                                        "maxLength": 60
                                    },
                                    "media_url": {
                                        "type": "string",
                                        "description": "Publicly reachable file to send as the message. WhatsApp fetches it directly, so it cannot sit behind authentication.",
                                        "maxLength": 2048,
                                        "format": "uri"
                                    },
                                    "media_type": {
                                        "type": "string",
                                        "description": "The kind of media at `media_url` (image, video, audio, document, sticker). Defaults to `message_type`.",
                                        "maxLength": 32
                                    },
                                    "template": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "Provider template name, language and components. Requires a nonempty name. Cannot be combined with media or interactive payloads.",
                                        "required": [
                                            "name"
                                        ],
                                        "properties": {
                                            "name": {
                                                "type": "string",
                                                "maxLength": 191,
                                                "description": "Template name exactly as approved in your WhatsApp Business Account."
                                            },
                                            "language": {
                                                "type": "string",
                                                "maxLength": 20,
                                                "description": "Template language code, e.g. `en` or `sw`. Defaults to `en`."
                                            },
                                            "components": {
                                                "type": "array",
                                                "items": {
                                                    "type": "object",
                                                    "additionalProperties": true
                                                },
                                                "description": "Template variables in WhatsApp's own `components` shape \u2014 one entry per header, body or button that takes a parameter."
                                            }
                                        }
                                    },
                                    "interactive": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "Provider-shaped interactive payload. Buttons and lists are normalized; other supported interactive types are passed through for provider validation. Cannot be combined with top-level media or template."
                                    },
                                    "reaction": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "Requires a nonempty emoji and a target provider message ID in message_id or in_reply_to_gateway_id. Cannot be combined with text/media/template/interactive.",
                                        "required": [
                                            "emoji"
                                        ],
                                        "properties": {
                                            "emoji": {
                                                "type": "string",
                                                "maxLength": 16,
                                                "description": "Nonempty reaction emoji. Empty-emoji removal is not supported by this REST route."
                                            },
                                            "message_id": {
                                                "type": "string",
                                                "maxLength": 191,
                                                "description": "The `gateway_message_id` of the message being reacted to."
                                            }
                                        }
                                    },
                                    "in_reply_to_gateway_id": {
                                        "type": "string",
                                        "description": "Quote an earlier message: the `gateway_message_id` of the message being replied to. It shows in the chat as a reply to that bubble.",
                                        "maxLength": 191
                                    },
                                    "sender_id": {
                                        "type": "string",
                                        "maxLength": 64,
                                        "description": "WhatsApp phone number id to send from, when the account has more than one. Defaults to the account default. `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself)."
                                    },
                                    "schedule_time": {
                                        "type": "string",
                                        "description": "Optional future send time. Use ISO8601 with an explicit offset; past times do not delay.",
                                        "maxLength": 100
                                    }
                                },
                                "anyOf": [
                                    {
                                        "required": [
                                            "recipient"
                                        ]
                                    },
                                    {
                                        "required": [
                                            "recipients"
                                        ]
                                    }
                                ],
                                "description": "Supply recipient and/or recipients. Inputs are merged and exact duplicates removed. Message/body and payload combinations follow this endpoint description. Reaction excludes every other payload; template excludes top-level media/interactive; interactive excludes top-level media. Media message types require media_url."
                            },
                            "examples": {
                                "default": {
                                    "summary": "Text message",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message": "Hello from the API"
                                    }
                                },
                                "text": {
                                    "summary": "Text",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "text",
                                        "message": "Hello, this is a plain text message."
                                    }
                                },
                                "image": {
                                    "summary": "Image",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "image",
                                        "media_url": "https://example.com/image.png",
                                        "message": "Optional caption"
                                    }
                                },
                                "video": {
                                    "summary": "Video",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "video",
                                        "media_url": "https://example.com/video.mp4",
                                        "message": "Optional caption"
                                    }
                                },
                                "audio": {
                                    "summary": "Audio",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "audio",
                                        "media_url": "https://example.com/audio.ogg"
                                    }
                                },
                                "document": {
                                    "summary": "Document",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "document",
                                        "media_url": "https://example.com/file.pdf",
                                        "message": "Optional filename or caption"
                                    }
                                },
                                "sticker": {
                                    "summary": "Sticker",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "sticker",
                                        "media_url": "https://example.com/sticker.webp"
                                    }
                                },
                                "template": {
                                    "summary": "Template",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "template",
                                        "template": {
                                            "name": "welcome_template",
                                            "language": "en",
                                            "components": []
                                        }
                                    }
                                },
                                "interactive_button": {
                                    "summary": "Interactive (buttons)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "button",
                                            "body": {
                                                "text": "Choose one"
                                            },
                                            "action": {
                                                "buttons": [
                                                    {
                                                        "id": "yes",
                                                        "title": "Yes"
                                                    },
                                                    {
                                                        "id": "no",
                                                        "title": "No"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                },
                                "interactive_list": {
                                    "summary": "Interactive (list)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "list",
                                            "body": {
                                                "text": "Select an option"
                                            },
                                            "action": {
                                                "button": "View options",
                                                "sections": [
                                                    {
                                                        "title": "Section 1",
                                                        "rows": [
                                                            {
                                                                "id": "opt_1",
                                                                "title": "Option 1",
                                                                "description": "First choice"
                                                            },
                                                            {
                                                                "id": "opt_2",
                                                                "title": "Option 2",
                                                                "description": "Second choice"
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                },
                                "reaction": {
                                    "summary": "Reaction",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "reaction",
                                        "reaction": {
                                            "emoji": "\ud83d\udc4d",
                                            "message_id": "wamid.xxxxx"
                                        }
                                    }
                                },
                                "location": {
                                    "summary": "Location pin",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "location",
                                        "location": {
                                            "latitude": -6.7924,
                                            "longitude": 39.2083,
                                            "name": "Momo Telecom HQ",
                                            "address": "Dar es Salaam, Tanzania"
                                        }
                                    }
                                },
                                "contacts_vcard": {
                                    "summary": "Contact card (vCard)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "contacts",
                                        "contacts": [
                                            {
                                                "name": {
                                                    "formatted_name": "Asha Mwita",
                                                    "first_name": "Asha",
                                                    "last_name": "Mwita"
                                                },
                                                "phones": [
                                                    {
                                                        "phone": "+255700123456",
                                                        "type": "WORK",
                                                        "wa_id": "255700123456"
                                                    }
                                                ],
                                                "emails": [
                                                    {
                                                        "email": "asha@example.com",
                                                        "type": "WORK"
                                                    }
                                                ],
                                                "org": {
                                                    "company": "Momo Telecom",
                                                    "title": "Account Manager"
                                                }
                                            }
                                        ]
                                    }
                                },
                                "interactive_cta_url": {
                                    "summary": "Interactive \u2014 call-to-action URL button",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "cta_url",
                                            "header": {
                                                "type": "text",
                                                "text": "Track your order"
                                            },
                                            "body": {
                                                "text": "Your order #4521 has shipped. Tap below to track delivery in real time."
                                            },
                                            "footer": {
                                                "text": "Powered by Momo Business"
                                            },
                                            "action": {
                                                "name": "cta_url",
                                                "parameters": {
                                                    "display_text": "Track order",
                                                    "url": "https://acme.example.com/orders/4521"
                                                }
                                            }
                                        }
                                    }
                                },
                                "interactive_flow": {
                                    "summary": "Interactive \u2014 WhatsApp Flow",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "flow",
                                            "header": {
                                                "type": "text",
                                                "text": "Book an appointment"
                                            },
                                            "body": {
                                                "text": "Pick a time slot that works for you."
                                            },
                                            "footer": {
                                                "text": "Takes 60 seconds"
                                            },
                                            "action": {
                                                "name": "flow",
                                                "parameters": {
                                                    "flow_message_version": "3",
                                                    "flow_token": "FLOW_TOKEN_FROM_BACKEND",
                                                    "flow_id": "1234567890123456",
                                                    "flow_cta": "Book now",
                                                    "flow_action": "navigate",
                                                    "flow_action_payload": {
                                                        "screen": "APPOINTMENT_SCREEN"
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "interactive_image_header": {
                                    "summary": "Interactive buttons with image header",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "button",
                                            "header": {
                                                "type": "image",
                                                "image": {
                                                    "link": "https://cdn.example.com/promo.jpg"
                                                }
                                            },
                                            "body": {
                                                "text": "Limited-time offer \u2014 30% off today only."
                                            },
                                            "action": {
                                                "buttons": [
                                                    {
                                                        "type": "reply",
                                                        "reply": {
                                                            "id": "shop_now",
                                                            "title": "Shop now"
                                                        }
                                                    },
                                                    {
                                                        "type": "reply",
                                                        "reply": {
                                                            "id": "remind_later",
                                                            "title": "Remind me later"
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                },
                                "product_single": {
                                    "summary": "Product (single item from a catalogue)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "product",
                                            "body": {
                                                "text": "Check out this laptop."
                                            },
                                            "action": {
                                                "catalog_id": "26191517010530753",
                                                "product_retailer_id": "SKU-LAPTOP-X1"
                                            }
                                        }
                                    }
                                },
                                "product_list": {
                                    "summary": "Product list (up to 30 items, 10 sections)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "product_list",
                                            "header": {
                                                "type": "text",
                                                "text": "Top picks"
                                            },
                                            "body": {
                                                "text": "Tap any item to see details and add to cart."
                                            },
                                            "footer": {
                                                "text": "Free delivery on orders over TZS 50,000"
                                            },
                                            "action": {
                                                "catalog_id": "26191517010530753",
                                                "sections": [
                                                    {
                                                        "title": "Laptops",
                                                        "product_items": [
                                                            {
                                                                "product_retailer_id": "SKU-LAPTOP-X1"
                                                            },
                                                            {
                                                                "product_retailer_id": "SKU-LAPTOP-AIR"
                                                            }
                                                        ]
                                                    },
                                                    {
                                                        "title": "Phones",
                                                        "product_items": [
                                                            {
                                                                "product_retailer_id": "SKU-PHONE-15"
                                                            }
                                                        ]
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                },
                                "catalog_message": {
                                    "summary": "Full catalogue (storefront entry point)",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "interactive",
                                        "interactive": {
                                            "type": "catalog_message",
                                            "body": {
                                                "text": "Browse our entire catalogue."
                                            },
                                            "action": {
                                                "name": "catalog_message",
                                                "parameters": {
                                                    "thumbnail_product_retailer_id": "SKU-LAPTOP-X1"
                                                }
                                            }
                                        }
                                    }
                                },
                                "template_with_components": {
                                    "summary": "Template with header image + body params + URL button",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "template",
                                        "template": {
                                            "name": "order_shipped",
                                            "language": "en_US",
                                            "components": [
                                                {
                                                    "type": "header",
                                                    "parameters": [
                                                        {
                                                            "type": "image",
                                                            "image": {
                                                                "link": "https://cdn.example.com/box.jpg"
                                                            }
                                                        }
                                                    ]
                                                },
                                                {
                                                    "type": "body",
                                                    "parameters": [
                                                        {
                                                            "type": "text",
                                                            "text": "Asha"
                                                        },
                                                        {
                                                            "type": "text",
                                                            "text": "4521"
                                                        },
                                                        {
                                                            "type": "text",
                                                            "text": "Tomorrow 9\u201311am"
                                                        }
                                                    ]
                                                },
                                                {
                                                    "type": "button",
                                                    "sub_type": "url",
                                                    "index": "0",
                                                    "parameters": [
                                                        {
                                                            "type": "text",
                                                            "text": "4521"
                                                        }
                                                    ]
                                                }
                                            ]
                                        }
                                    }
                                },
                                "reply_in_thread": {
                                    "summary": "Reply that quotes a previous message",
                                    "value": {
                                        "recipient": "255700111222",
                                        "message_type": "text",
                                        "message": "Got it \u2014 see you tomorrow!",
                                        "in_reply_to_gateway_id": "wamid.HBgMMjU1NzAwMTExMjIyFQIAERgSREYx..."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "One message record per recipient. `data.messages[].status` is the delivery state at the moment we answered; watch the `message.*` webhooks for what happens after.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "messages"
                                            ],
                                            "properties": {
                                                "messages": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Message",
                                                        "description": "The message record."
                                                    },
                                                    "description": "One record per recipient, in the order they were given."
                                                }
                                            },
                                            "description": "The messages this call created."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "messages": [
                                                    {
                                                        "id": 300,
                                                        "uid": "msg_01JXYZWA01",
                                                        "direction": "outbound",
                                                        "channel_type": "whatsapp",
                                                        "recipient": "255700111222",
                                                        "body": "Interactive message",
                                                        "status": "sent",
                                                        "metadata": {
                                                            "interactive": {
                                                                "type": "button"
                                                            }
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Invalid API token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation or payload combination error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Reaction cannot be combined with text, media, template, or interactive payload."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp": {
            "get": {
                "tags": [
                    "WhatsApp"
                ],
                "operationId": "v3WhatsAppList",
                "summary": "List WhatsApp messages",
                "description": "Returns tenant-scoped WhatsApp message logs with pagination.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/MessageStatus"
                    },
                    {
                        "$ref": "#/components/parameters/MessageDirection"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "WhatsApp collection.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items",
                                                "pagination"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Message",
                                                        "description": "The message record."
                                                    },
                                                    "description": "The messages on this page, newest first."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state for this list: where you are and whether more pages follow."
                                                }
                                            },
                                            "description": "A page of messages and its page state."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "items": [
                                                    {
                                                        "id": 300,
                                                        "uid": "msg_01JXYZWA01",
                                                        "direction": "outbound",
                                                        "channel_type": "whatsapp",
                                                        "recipient": "255700111222",
                                                        "body": "Interactive message",
                                                        "status": "queued"
                                                    }
                                                ],
                                                "pagination": {
                                                    "current_page": 1,
                                                    "per_page": 20,
                                                    "last_page": 1,
                                                    "total": 1,
                                                    "has_more_pages": false
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Missing bearer token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/{uid}": {
            "get": {
                "tags": [
                    "WhatsApp"
                ],
                "operationId": "v3WhatsAppShow",
                "summary": "Get a WhatsApp message",
                "description": "Fetches one WhatsApp message by public uid.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/MessageUid"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Single WhatsApp message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Message",
                                            "description": "The message record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 300,
                                                "uid": "msg_01JXYZWA01",
                                                "direction": "outbound",
                                                "channel_type": "whatsapp",
                                                "recipient": "255700111222",
                                                "body": "Interactive message",
                                                "status": "delivered"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Message not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Message not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups": {
            "get": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsList",
                "x-permission": "communications.groups.view",
                "x-permission-scope": "controller",
                "summary": "List WhatsApp groups",
                "description": "Groups created from the account's WhatsApp numbers. Deleted groups are left out unless `status=deleted` or `status=all`.",
                "parameters": [
                    {
                        "name": "sender_id",
                        "in": "query",
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only groups on this business number (phone_number_id or display number). `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself).",
                        "example": "243438852181644"
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "creating",
                                "active",
                                "suspended",
                                "failed",
                                "deleted",
                                "all"
                            ]
                        },
                        "example": "active",
                        "description": "creating (waiting for WhatsApp), active, suspended (by WhatsApp, for policy), deleted, or failed (WhatsApp refused to create it; see last_error)."
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 20
                        },
                        "example": 20,
                        "description": "limit"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of groups.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppGroup"
                                                    },
                                                    "description": "The groups on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Paging information."
                                                }
                                            },
                                            "description": "A page of groups."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "items": [
                                                    {
                                                        "id": 12,
                                                        "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                        "request_id": "b5c1\u2026",
                                                        "phone_number_id": "243438852181644",
                                                        "waba_id": "1029384756",
                                                        "subject": "VIP customers \u2014 September",
                                                        "description": "Offers first.",
                                                        "join_approval_mode": "auto_approve",
                                                        "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                        "status": "active",
                                                        "participant_count": 5,
                                                        "max_participants": 8,
                                                        "seats_left": 2,
                                                        "pending_join_requests": 0,
                                                        "conversation_id": 8812,
                                                        "invite_template_id": 41,
                                                        "last_message_at": "2026-09-07T10:12:00+03:00",
                                                        "last_error": null,
                                                        "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                        "created_at": "2026-09-01T08:00:00+03:00",
                                                        "updated_at": "2026-09-07T10:12:00+03:00"
                                                    }
                                                ],
                                                "pagination": {
                                                    "current_page": 1,
                                                    "per_page": 20,
                                                    "last_page": 1,
                                                    "total": 1,
                                                    "has_more_pages": false
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsCreate",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Create a WhatsApp group",
                "description": "Creates a group from a business number. WhatsApp confirms it a moment later: the group starts as `creating` and becomes `active`, with its `meta_group_id` and `invite_link`, when the confirmation webhook arrives. Invitees, if given, are sent the invite template once it is active.\n\nNeeds an Official Business Account (the green tick); otherwise WhatsApp answers code 131215 and this endpoint returns 422. Nobody can be added to a group directly \u2014 people join by tapping the link.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "sender_id": {
                                        "type": "string",
                                        "description": "The business number; the account's default WhatsApp number when omitted. `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself)."
                                    },
                                    "subject": {
                                        "type": "string",
                                        "maxLength": 128,
                                        "description": "The group name, up to 128 characters."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 2048,
                                        "description": "What the group is for; members see it before joining. Up to 2048 characters."
                                    },
                                    "join_approval_mode": {
                                        "type": "string",
                                        "enum": [
                                            "auto_approve",
                                            "approval_required"
                                        ],
                                        "default": "auto_approve",
                                        "description": "auto_approve: anyone with the link joins. approval_required: the business approves each request."
                                    },
                                    "invite_template": {
                                        "type": "string",
                                        "description": "Name of an approved group-invite template."
                                    },
                                    "invitees": {
                                        "type": "array",
                                        "maxItems": 7,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Phones to invite once the group is confirmed."
                                    }
                                },
                                "required": [
                                    "subject"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "subject": "VIP customers \u2014 September",
                                        "description": "Offers first.",
                                        "join_approval_mode": "auto_approve",
                                        "invite_template": "group_invite_link",
                                        "invitees": [
                                            "255711000001",
                                            "255711000002"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Group requested (or, rarely, created at once).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppGroupDetail",
                                            "description": "Group requested (or, rarely, created at once)."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 12,
                                                "meta_group_id": null,
                                                "request_id": "b5c1\u2026",
                                                "phone_number_id": "243438852181644",
                                                "waba_id": "1029384756",
                                                "subject": "VIP customers \u2014 September",
                                                "description": "Offers first.",
                                                "join_approval_mode": "auto_approve",
                                                "invite_link": null,
                                                "status": "creating",
                                                "participant_count": 5,
                                                "max_participants": 8,
                                                "seats_left": 2,
                                                "pending_join_requests": 0,
                                                "conversation_id": 8812,
                                                "invite_template_id": 41,
                                                "last_message_at": "2026-09-07T10:12:00+03:00",
                                                "last_error": null,
                                                "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                "created_at": "2026-09-01T08:00:00+03:00",
                                                "updated_at": "2026-09-07T10:12:00+03:00",
                                                "participants": [],
                                                "join_requests": [],
                                                "invite_template": {
                                                    "id": 41,
                                                    "name": "group_invite_link",
                                                    "language": "en",
                                                    "whatsapp_status": "approved"
                                                },
                                                "events": []
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}": {
            "get": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsShow",
                "x-permission": "communications.groups.view",
                "x-permission-scope": "controller",
                "summary": "Get a WhatsApp group",
                "description": "One group with its members, pending join requests, invite link and recent activity.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The group.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppGroupDetail",
                                            "description": "The group."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 12,
                                                "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                "request_id": "b5c1\u2026",
                                                "phone_number_id": "243438852181644",
                                                "waba_id": "1029384756",
                                                "subject": "VIP customers \u2014 September",
                                                "description": "Offers first.",
                                                "join_approval_mode": "auto_approve",
                                                "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                "status": "active",
                                                "participant_count": 5,
                                                "max_participants": 8,
                                                "seats_left": 2,
                                                "pending_join_requests": 0,
                                                "conversation_id": 8812,
                                                "invite_template_id": 41,
                                                "last_message_at": "2026-09-07T10:12:00+03:00",
                                                "last_error": null,
                                                "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                "created_at": "2026-09-01T08:00:00+03:00",
                                                "updated_at": "2026-09-07T10:12:00+03:00",
                                                "participants": [
                                                    {
                                                        "id": 1,
                                                        "wa_id": "255711000001",
                                                        "display_name": "Asha",
                                                        "status": "member",
                                                        "invited_at": "2026-09-01T08:05:00+03:00",
                                                        "joined_at": "2026-09-01T08:09:00+03:00",
                                                        "left_at": null,
                                                        "reason": "invite_link",
                                                        "last_error": null
                                                    }
                                                ],
                                                "join_requests": [
                                                    {
                                                        "id": 3,
                                                        "join_request_id": "JR-1",
                                                        "wa_id": "255711000005",
                                                        "status": "pending",
                                                        "requested_at": "2026-09-07T10:00:00+03:00",
                                                        "resolved_at": null
                                                    }
                                                ],
                                                "invite_template": {
                                                    "id": 41,
                                                    "name": "group_invite_link",
                                                    "language": "en",
                                                    "whatsapp_status": "approved"
                                                },
                                                "events": [
                                                    {
                                                        "id": 90,
                                                        "type": "group.participant_joined",
                                                        "actor": "participant",
                                                        "payload": {
                                                            "wa_ids": [
                                                                "255711000001"
                                                            ],
                                                            "reason": "invite_link"
                                                        },
                                                        "occurred_at": "2026-09-01T08:09:00+03:00"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsUpdate",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Update a group's subject or description",
                "description": "Applied optimistically; WhatsApp confirms through the settings webhook and the group is re-synced if it refused.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "subject": {
                                        "type": "string",
                                        "maxLength": 128,
                                        "description": "The group name, up to 128 characters."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 2048,
                                        "description": "What the group is for; members see it before joining. Up to 2048 characters."
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "subject": "VIP customers \u2014 October"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The group.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppGroupDetail",
                                            "description": "The group."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 12,
                                                "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                "request_id": "b5c1\u2026",
                                                "phone_number_id": "243438852181644",
                                                "waba_id": "1029384756",
                                                "subject": "VIP customers \u2014 September",
                                                "description": "Offers first.",
                                                "join_approval_mode": "auto_approve",
                                                "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                "status": "active",
                                                "participant_count": 5,
                                                "max_participants": 8,
                                                "seats_left": 2,
                                                "pending_join_requests": 0,
                                                "conversation_id": 8812,
                                                "invite_template_id": 41,
                                                "last_message_at": "2026-09-07T10:12:00+03:00",
                                                "last_error": null,
                                                "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                "created_at": "2026-09-01T08:00:00+03:00",
                                                "updated_at": "2026-09-07T10:12:00+03:00",
                                                "participants": [
                                                    {
                                                        "id": 1,
                                                        "wa_id": "255711000001",
                                                        "display_name": "Asha",
                                                        "status": "member",
                                                        "invited_at": "2026-09-01T08:05:00+03:00",
                                                        "joined_at": "2026-09-01T08:09:00+03:00",
                                                        "left_at": null,
                                                        "reason": "invite_link",
                                                        "last_error": null
                                                    }
                                                ],
                                                "join_requests": [
                                                    {
                                                        "id": 3,
                                                        "join_request_id": "JR-1",
                                                        "wa_id": "255711000005",
                                                        "status": "pending",
                                                        "requested_at": "2026-09-07T10:00:00+03:00",
                                                        "resolved_at": null
                                                    }
                                                ],
                                                "invite_template": {
                                                    "id": 41,
                                                    "name": "group_invite_link",
                                                    "language": "en",
                                                    "whatsapp_status": "approved"
                                                },
                                                "events": [
                                                    {
                                                        "id": 90,
                                                        "type": "group.participant_joined",
                                                        "actor": "participant",
                                                        "payload": {
                                                            "wa_ids": [
                                                                "255711000001"
                                                            ],
                                                            "reason": "invite_link"
                                                        },
                                                        "occurred_at": "2026-09-01T08:09:00+03:00"
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsDelete",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Delete a WhatsApp group",
                "description": "Removes everyone and closes the thread. The thread and its history stay readable.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The group, now deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppGroup",
                                            "description": "The group, now deleted."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 12,
                                                "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                "request_id": "b5c1\u2026",
                                                "phone_number_id": "243438852181644",
                                                "waba_id": "1029384756",
                                                "subject": "VIP customers \u2014 September",
                                                "description": "Offers first.",
                                                "join_approval_mode": "auto_approve",
                                                "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                "status": "deleted",
                                                "participant_count": 5,
                                                "max_participants": 8,
                                                "seats_left": 2,
                                                "pending_join_requests": 0,
                                                "conversation_id": 8812,
                                                "invite_template_id": 41,
                                                "last_message_at": "2026-09-07T10:12:00+03:00",
                                                "last_error": null,
                                                "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                "created_at": "2026-09-01T08:00:00+03:00",
                                                "updated_at": "2026-09-07T10:12:00+03:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}/invite-link/reset": {
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsResetInviteLink",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Reset the invite link",
                "description": "Issues a new link; the old one stops working at once.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The new link.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "invite_link": {
                                                    "type": "string",
                                                    "description": "The chat.whatsapp.com link people tap to join. Null until WhatsApp confirms the group."
                                                },
                                                "group": {
                                                    "$ref": "#/components/schemas/WhatsAppGroup",
                                                    "description": "The group after the change."
                                                }
                                            },
                                            "description": "The new link."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "invite_link": "https://chat.whatsapp.com/NewLink9",
                                                "group": {
                                                    "id": 12,
                                                    "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                    "request_id": "b5c1\u2026",
                                                    "phone_number_id": "243438852181644",
                                                    "waba_id": "1029384756",
                                                    "subject": "VIP customers \u2014 September",
                                                    "description": "Offers first.",
                                                    "join_approval_mode": "auto_approve",
                                                    "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                    "status": "active",
                                                    "participant_count": 5,
                                                    "max_participants": 8,
                                                    "seats_left": 2,
                                                    "pending_join_requests": 0,
                                                    "conversation_id": 8812,
                                                    "invite_template_id": 41,
                                                    "last_message_at": "2026-09-07T10:12:00+03:00",
                                                    "last_error": null,
                                                    "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                    "created_at": "2026-09-01T08:00:00+03:00",
                                                    "updated_at": "2026-09-07T10:12:00+03:00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}/invites": {
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsInvite",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Invite people to a group",
                "description": "Sends each recipient the approved invite-link template as a normal 1:1 template message (billed as such). They join by tapping the link; the roster updates from the webhook.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "recipients": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 7,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Phone numbers in international format, without the plus sign."
                                    },
                                    "template": {
                                        "type": "string",
                                        "description": "An approved invite template name; the group's own, or the account's first matching one, when omitted."
                                    }
                                },
                                "required": [
                                    "recipients"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "recipients": [
                                            "255711000003"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Who was invited and who was not.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "sent": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Recipients the invite was queued for."
                                                },
                                                "failed": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "phone": {
                                                                "type": "string",
                                                                "description": "The recipient."
                                                            },
                                                            "reason": {
                                                                "type": "string",
                                                                "description": "How they got here: invite_link, left, removed_by_business, sync, group_deleted."
                                                            }
                                                        }
                                                    },
                                                    "description": "Recipients it was not sent to, with the reason."
                                                },
                                                "group": {
                                                    "$ref": "#/components/schemas/WhatsAppGroup",
                                                    "description": "The group after the change."
                                                }
                                            },
                                            "description": "Who was invited and who was not."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "sent": [
                                                    "255711000003"
                                                ],
                                                "failed": [],
                                                "group": {
                                                    "id": 12,
                                                    "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                    "request_id": "b5c1\u2026",
                                                    "phone_number_id": "243438852181644",
                                                    "waba_id": "1029384756",
                                                    "subject": "VIP customers \u2014 September",
                                                    "description": "Offers first.",
                                                    "join_approval_mode": "auto_approve",
                                                    "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                    "status": "active",
                                                    "participant_count": 5,
                                                    "max_participants": 8,
                                                    "seats_left": 2,
                                                    "pending_join_requests": 0,
                                                    "conversation_id": 8812,
                                                    "invite_template_id": 41,
                                                    "last_message_at": "2026-09-07T10:12:00+03:00",
                                                    "last_error": null,
                                                    "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                    "created_at": "2026-09-01T08:00:00+03:00",
                                                    "updated_at": "2026-09-07T10:12:00+03:00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}/participants": {
            "delete": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsRemoveParticipants",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Remove people from a group",
                "description": "Up to 8 per call, by phone number or wa_id.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "participants": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 8,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Everyone ever invited into or seen in the group, with their current state."
                                    }
                                },
                                "required": [
                                    "participants"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "participants": [
                                            "255711000002"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Who was removed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "removed": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "People removed."
                                                },
                                                "failed": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "Recipients it was not sent to, with the reason."
                                                },
                                                "group": {
                                                    "$ref": "#/components/schemas/WhatsAppGroupDetail",
                                                    "description": "The group after the change."
                                                }
                                            },
                                            "description": "Who was removed."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "removed": [
                                                    "255711000002"
                                                ],
                                                "failed": [],
                                                "group": {
                                                    "id": 12,
                                                    "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                    "request_id": "b5c1\u2026",
                                                    "phone_number_id": "243438852181644",
                                                    "waba_id": "1029384756",
                                                    "subject": "VIP customers \u2014 September",
                                                    "description": "Offers first.",
                                                    "join_approval_mode": "auto_approve",
                                                    "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                    "status": "active",
                                                    "participant_count": 5,
                                                    "max_participants": 8,
                                                    "seats_left": 2,
                                                    "pending_join_requests": 0,
                                                    "conversation_id": 8812,
                                                    "invite_template_id": 41,
                                                    "last_message_at": "2026-09-07T10:12:00+03:00",
                                                    "last_error": null,
                                                    "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                    "created_at": "2026-09-01T08:00:00+03:00",
                                                    "updated_at": "2026-09-07T10:12:00+03:00",
                                                    "participants": [
                                                        {
                                                            "id": 1,
                                                            "wa_id": "255711000001",
                                                            "display_name": "Asha",
                                                            "status": "member",
                                                            "invited_at": "2026-09-01T08:05:00+03:00",
                                                            "joined_at": "2026-09-01T08:09:00+03:00",
                                                            "left_at": null,
                                                            "reason": "invite_link",
                                                            "last_error": null
                                                        }
                                                    ],
                                                    "join_requests": [
                                                        {
                                                            "id": 3,
                                                            "join_request_id": "JR-1",
                                                            "wa_id": "255711000005",
                                                            "status": "pending",
                                                            "requested_at": "2026-09-07T10:00:00+03:00",
                                                            "resolved_at": null
                                                        }
                                                    ],
                                                    "invite_template": {
                                                        "id": 41,
                                                        "name": "group_invite_link",
                                                        "language": "en",
                                                        "whatsapp_status": "approved"
                                                    },
                                                    "events": [
                                                        {
                                                            "id": 90,
                                                            "type": "group.participant_joined",
                                                            "actor": "participant",
                                                            "payload": {
                                                                "wa_ids": [
                                                                    "255711000001"
                                                                ],
                                                                "reason": "invite_link"
                                                            },
                                                            "occurred_at": "2026-09-01T08:09:00+03:00"
                                                        }
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}/join-requests": {
            "get": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsJoinRequests",
                "x-permission": "communications.groups.view",
                "x-permission-scope": "controller",
                "summary": "List join requests",
                "description": "Everyone who asked to join an approval-required group, newest first.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Join requests.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppGroupJoinRequest"
                                                    },
                                                    "description": "The rows on this page."
                                                }
                                            },
                                            "description": "Join requests."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "items": [
                                                    {
                                                        "id": 3,
                                                        "join_request_id": "JR-1",
                                                        "wa_id": "255711000005",
                                                        "status": "pending",
                                                        "requested_at": "2026-09-07T10:00:00+03:00",
                                                        "resolved_at": null
                                                    }
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}/join-requests/approve": {
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsApproveJoinRequests",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Approve join requests",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "join_requests": {
                                        "type": "array",
                                        "minItems": 1,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "join_request_id values from the list or the group.join_requested webhook."
                                    }
                                },
                                "required": [
                                    "join_requests"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "join_requests": [
                                            "JR-1"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result per request.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "approved": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Requests approved."
                                                },
                                                "failed": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "Recipients it was not sent to, with the reason."
                                                },
                                                "group": {
                                                    "$ref": "#/components/schemas/WhatsAppGroupDetail",
                                                    "description": "The group after the change."
                                                }
                                            },
                                            "description": "Result per request."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "approved": [
                                                    "JR-1"
                                                ],
                                                "failed": [],
                                                "group": {
                                                    "id": 12,
                                                    "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                    "request_id": "b5c1\u2026",
                                                    "phone_number_id": "243438852181644",
                                                    "waba_id": "1029384756",
                                                    "subject": "VIP customers \u2014 September",
                                                    "description": "Offers first.",
                                                    "join_approval_mode": "auto_approve",
                                                    "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                    "status": "active",
                                                    "participant_count": 5,
                                                    "max_participants": 8,
                                                    "seats_left": 2,
                                                    "pending_join_requests": 0,
                                                    "conversation_id": 8812,
                                                    "invite_template_id": 41,
                                                    "last_message_at": "2026-09-07T10:12:00+03:00",
                                                    "last_error": null,
                                                    "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                    "created_at": "2026-09-01T08:00:00+03:00",
                                                    "updated_at": "2026-09-07T10:12:00+03:00",
                                                    "participants": [
                                                        {
                                                            "id": 1,
                                                            "wa_id": "255711000001",
                                                            "display_name": "Asha",
                                                            "status": "member",
                                                            "invited_at": "2026-09-01T08:05:00+03:00",
                                                            "joined_at": "2026-09-01T08:09:00+03:00",
                                                            "left_at": null,
                                                            "reason": "invite_link",
                                                            "last_error": null
                                                        }
                                                    ],
                                                    "join_requests": [
                                                        {
                                                            "id": 3,
                                                            "join_request_id": "JR-1",
                                                            "wa_id": "255711000005",
                                                            "status": "pending",
                                                            "requested_at": "2026-09-07T10:00:00+03:00",
                                                            "resolved_at": null
                                                        }
                                                    ],
                                                    "invite_template": {
                                                        "id": 41,
                                                        "name": "group_invite_link",
                                                        "language": "en",
                                                        "whatsapp_status": "approved"
                                                    },
                                                    "events": [
                                                        {
                                                            "id": 90,
                                                            "type": "group.participant_joined",
                                                            "actor": "participant",
                                                            "payload": {
                                                                "wa_ids": [
                                                                    "255711000001"
                                                                ],
                                                                "reason": "invite_link"
                                                            },
                                                            "occurred_at": "2026-09-01T08:09:00+03:00"
                                                        }
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "description": "Lets the people in the request into the group. Their join shows up on the group.participant_joined webhook."
            }
        },
        "/api/v3/whatsapp/groups/{id}/join-requests/reject": {
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsRejectJoinRequests",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Reject join requests",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "join_requests": {
                                        "type": "array",
                                        "minItems": 1,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "join_request_id values from the list or the group.join_requested webhook."
                                    }
                                },
                                "required": [
                                    "join_requests"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "join_requests": [
                                            "JR-1"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Result per request.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "rejected": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Requests rejected."
                                                },
                                                "failed": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "Recipients it was not sent to, with the reason."
                                                },
                                                "group": {
                                                    "$ref": "#/components/schemas/WhatsAppGroupDetail",
                                                    "description": "The group after the change."
                                                }
                                            },
                                            "description": "Result per request."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "rejected": [
                                                    "JR-1"
                                                ],
                                                "failed": [],
                                                "group": {
                                                    "id": 12,
                                                    "meta_group_id": "Y2FwaV9ncm91cDo6MTIzNDU2",
                                                    "request_id": "b5c1\u2026",
                                                    "phone_number_id": "243438852181644",
                                                    "waba_id": "1029384756",
                                                    "subject": "VIP customers \u2014 September",
                                                    "description": "Offers first.",
                                                    "join_approval_mode": "auto_approve",
                                                    "invite_link": "https://chat.whatsapp.com/AbCdEf123",
                                                    "status": "active",
                                                    "participant_count": 5,
                                                    "max_participants": 8,
                                                    "seats_left": 2,
                                                    "pending_join_requests": 0,
                                                    "conversation_id": 8812,
                                                    "invite_template_id": 41,
                                                    "last_message_at": "2026-09-07T10:12:00+03:00",
                                                    "last_error": null,
                                                    "last_synced_at": "2026-09-07T09:00:00+03:00",
                                                    "created_at": "2026-09-01T08:00:00+03:00",
                                                    "updated_at": "2026-09-07T10:12:00+03:00",
                                                    "participants": [
                                                        {
                                                            "id": 1,
                                                            "wa_id": "255711000001",
                                                            "display_name": "Asha",
                                                            "status": "member",
                                                            "invited_at": "2026-09-01T08:05:00+03:00",
                                                            "joined_at": "2026-09-01T08:09:00+03:00",
                                                            "left_at": null,
                                                            "reason": "invite_link",
                                                            "last_error": null
                                                        }
                                                    ],
                                                    "join_requests": [
                                                        {
                                                            "id": 3,
                                                            "join_request_id": "JR-1",
                                                            "wa_id": "255711000005",
                                                            "status": "pending",
                                                            "requested_at": "2026-09-07T10:00:00+03:00",
                                                            "resolved_at": null
                                                        }
                                                    ],
                                                    "invite_template": {
                                                        "id": 41,
                                                        "name": "group_invite_link",
                                                        "language": "en",
                                                        "whatsapp_status": "approved"
                                                    },
                                                    "events": [
                                                        {
                                                            "id": 90,
                                                            "type": "group.participant_joined",
                                                            "actor": "participant",
                                                            "payload": {
                                                                "wa_ids": [
                                                                    "255711000001"
                                                                ],
                                                                "reason": "invite_link"
                                                            },
                                                            "occurred_at": "2026-09-01T08:09:00+03:00"
                                                        }
                                                    ]
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "description": "Turns the people in the request away. They can ask again with the same link."
            }
        },
        "/api/v3/whatsapp/groups/{id}/messages": {
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsSendMessage",
                "x-permission": "communications.groups.manage, communications.send",
                "x-permission-scope": "controller",
                "summary": "Send a message into a group",
                "description": "Text, a media link, or an approved template, to everyone in the room. Text and media need a member to have written in the last 24 hours; a template always sends. WhatsApp bills one message per member it is delivered to. Buttons, lists, products and reactions are not accepted in groups.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "message": {
                                        "type": "string",
                                        "maxLength": 4096,
                                        "description": "The text, or the caption when media_url is given."
                                    },
                                    "media_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "A public URL to an image, video, audio file or document."
                                    },
                                    "media_type": {
                                        "type": "string",
                                        "enum": [
                                            "image",
                                            "video",
                                            "audio",
                                            "document"
                                        ],
                                        "description": "What the media is; document when omitted."
                                    },
                                    "template": {
                                        "type": "object",
                                        "properties": {
                                            "name": {
                                                "type": "string",
                                                "description": "Template name."
                                            },
                                            "language": {
                                                "type": "string",
                                                "description": "Template language code."
                                            },
                                            "components": {
                                                "type": "array",
                                                "items": {
                                                    "type": "object"
                                                },
                                                "description": "Template components, exactly as for /whatsapp/send."
                                            }
                                        },
                                        "required": [
                                            "name"
                                        ],
                                        "description": "An approved template."
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "message": "Ofa ya leo: 20% off hadi saa 12."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The queued message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Message",
                                            "description": "The queued message."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 901,
                                                "public_uid": "msg_01JXYZWG01",
                                                "conversation_id": 8812,
                                                "direction": "outbound",
                                                "body": "Ofa ya leo: 20% off hadi saa 12.",
                                                "status": "queued"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, communications.send, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/groups/{id}/pin": {
            "post": {
                "tags": [
                    "WhatsApp groups"
                ],
                "operationId": "v3WhatsAppGroupsPin",
                "x-permission": "communications.groups.manage",
                "x-permission-scope": "controller",
                "summary": "Pin or unpin a message",
                "description": "At most three pinned at a time; pinning a fourth unpins the oldest.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "message_uid": {
                                        "type": "string",
                                        "description": "The public uid of a delivered message in this group."
                                    },
                                    "pin": {
                                        "type": "boolean",
                                        "description": "true to pin, false to unpin."
                                    },
                                    "expiration_days": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 30,
                                        "description": "How long to keep it pinned; WhatsApp allows 1 to 30 days."
                                    }
                                },
                                "required": [
                                    "message_uid",
                                    "pin"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "message_uid": "msg_01JXYZWG01",
                                        "pin": true,
                                        "expiration_days": 7
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Done.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "pinned": {
                                                    "type": "boolean",
                                                    "description": "Whether the message is pinned now."
                                                }
                                            },
                                            "description": "Done."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "pinned": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Group not found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "WhatsApp refused the request, or the group cannot take it right now (not confirmed yet, suspended, deleted). Meta's error code, when there is one, is under errors.meta[0].code.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "WhatsApp suspended this group; nothing can be sent until the suspension clears."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold communications.groups.manage, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"communications.groups.manage\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contacts/{group_id}/store": {
            "post": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactsStore",
                "summary": "Create a contact",
                "description": "Stores one contact in a group using legacy fields and custom dynamic attributes. `POST /api/v3/contact-groups/{group}/contacts` is the same operation on the REST path, and `\u2026/contacts/batch` takes up to 500 at once.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "PHONE": {
                                        "type": "string",
                                        "description": "The phone number, with or without the country code. Combined with `country_code` and normalised for storage.",
                                        "maxLength": 64
                                    },
                                    "country_code": {
                                        "type": "string",
                                        "description": "Explicit calling code, e.g. 255. The contact parser does not infer this from a +255 PHONE value when omitted.",
                                        "maxLength": 8
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Display name. When absent, FIRST_NAME and LAST_NAME are joined; when those are absent too, the phone number is used.",
                                        "maxLength": 160
                                    },
                                    "FIRST_NAME": {
                                        "type": "string",
                                        "description": "First name. Joined with LAST_NAME when `name` is absent."
                                    },
                                    "LAST_NAME": {
                                        "type": "string",
                                        "description": "Last name. Joined with FIRST_NAME when `name` is absent."
                                    },
                                    "is_subscribed": {
                                        "type": "boolean",
                                        "description": "Stored subscription flag. Defaults true on create and retains its value when omitted on update. Current campaign dispatch does not automatically filter this flag."
                                    },
                                    "phone_number": {
                                        "type": "string",
                                        "description": "Alias of PHONE. PHONE wins when both are supplied.",
                                        "maxLength": 64
                                    },
                                    "NAME": {
                                        "type": "string",
                                        "description": "Name alias used when name is absent."
                                    }
                                },
                                "additionalProperties": true,
                                "description": "PHONE or phone_number is required, including on PATCH. Name is recalculated and custom fields are replaced, not merged. Nonreserved top-level fields become custom_field_values. Reserved keys include PHONE, phone_number, country_code, name, NAME, FIRST_NAME, LAST_NAME, is_subscribed and _token.",
                                "anyOf": [
                                    {
                                        "required": [
                                            "PHONE"
                                        ]
                                    },
                                    {
                                        "required": [
                                            "phone_number"
                                        ]
                                    }
                                ]
                            },
                            "examples": {
                                "default": {
                                    "summary": "Minimal \u2014 only the phone number is required",
                                    "value": {
                                        "PHONE": "255700333444"
                                    }
                                },
                                "with_name": {
                                    "summary": "With name + structured first/last name",
                                    "value": {
                                        "PHONE": "255700333444",
                                        "name": "Asha Mwita",
                                        "FIRST_NAME": "Asha",
                                        "LAST_NAME": "Mwita"
                                    }
                                },
                                "with_country_code": {
                                    "summary": "Local phone format + explicit country code",
                                    "value": {
                                        "PHONE": "0700333444",
                                        "country_code": "TZ",
                                        "name": "Asha Mwita"
                                    }
                                },
                                "with_custom_fields": {
                                    "summary": "Custom merge fields (any keys you don't recognise become custom fields)",
                                    "value": {
                                        "PHONE": "255700333444",
                                        "FIRST_NAME": "Asha",
                                        "LAST_NAME": "Mwita",
                                        "CITY": "Dar es Salaam",
                                        "ACCOUNT_NUMBER": "AC-2204",
                                        "PLAN": "Pro",
                                        "RENEWAL_DATE": "2026-05-01"
                                    }
                                },
                                "opted_out": {
                                    "summary": "Mark contact as opted-out (won't receive campaigns)",
                                    "value": {
                                        "PHONE": "255700333444",
                                        "name": "Asha Mwita",
                                        "is_subscribed": false
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Contact created. Phone numbers are normalised to E.164 (international) format and de-duplicated within the group \u2014 re-posting the same PHONE returns the existing row.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Contact",
                                            "description": "The contact record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 66,
                                                "uid": "ctc_01JXYZ001",
                                                "group_id": 8,
                                                "group_uid": "grp_01JXYZABC",
                                                "name": "John Doe",
                                                "country_code": "255",
                                                "phone_number": "700333444",
                                                "full_phone_number": "255700333444",
                                                "is_subscribed": true,
                                                "custom_field_values": {
                                                    "CITY": "Dar es Salaam"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Contact group not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "PHONE": [
                                                    "The PHONE field is required."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    }
                },
                "x-permission": "contacts.create",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/contacts/{group_id}/search/{uid}": {
            "post": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactsShow",
                "summary": "Find a contact",
                "description": "Finds a single contact in a group by public uid. `GET /api/v3/contact-groups/{group}/contacts/{contact}` is the same operation on the REST path.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    },
                    {
                        "$ref": "#/components/parameters/ContactUid"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Single contact.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Contact",
                                            "description": "The contact record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 66,
                                                "uid": "ctc_01JXYZ001",
                                                "group_id": 8,
                                                "group_uid": "grp_01JXYZABC",
                                                "name": "John Doe",
                                                "country_code": "255",
                                                "phone_number": "700333444",
                                                "full_phone_number": "255700333444",
                                                "is_subscribed": true,
                                                "custom_field_values": {
                                                    "CITY": "Dar es Salaam"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Contact not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Contact not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    }
                },
                "x-permission": "contacts.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/contacts/{group_id}/update/{uid}": {
            "patch": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactsUpdate",
                "summary": "Update a contact",
                "description": "Changes exactly what you send. Custom fields MERGE into what is stored (send a key as `null` to remove it), and the name, number and subscription each keep their current value when the payload is silent about them; `PHONE` is required only when the number itself is changing.\n\nThis changed on 2026-09-14. Until then the endpoint replaced the whole custom-field map and renamed the contact after their phone number whenever `name` was absent, so a call meant only to flip `is_subscribed` destroyed data. A caller that followed the old advice \u2014 read, merge, send everything \u2014 is unaffected. `PATCH /api/v3/contact-groups/{group}/contacts/{contact}` is the same operation on the REST path.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    },
                    {
                        "$ref": "#/components/parameters/ContactUid"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "PHONE": {
                                        "type": "string",
                                        "description": "The phone number, with or without the country code. Combined with `country_code` and normalised for storage.",
                                        "maxLength": 64
                                    },
                                    "country_code": {
                                        "type": "string",
                                        "description": "Explicit calling code, e.g. 255. The contact parser does not infer this from a +255 PHONE value when omitted.",
                                        "maxLength": 8
                                    },
                                    "name": {
                                        "type": "string",
                                        "description": "Display name. When absent, FIRST_NAME and LAST_NAME are joined; when those are absent too, the phone number is used.",
                                        "maxLength": 160
                                    },
                                    "is_subscribed": {
                                        "type": "boolean",
                                        "description": "Stored subscription flag. Defaults true on create and retains its value when omitted on update. Current campaign dispatch does not automatically filter this flag."
                                    },
                                    "FIRST_NAME": {
                                        "type": "string",
                                        "description": "First name. Joined with LAST_NAME when `name` is absent."
                                    },
                                    "LAST_NAME": {
                                        "type": "string",
                                        "description": "Last name. Joined with FIRST_NAME when `name` is absent."
                                    },
                                    "phone_number": {
                                        "type": "string",
                                        "description": "Alias of PHONE. PHONE wins when both are supplied.",
                                        "maxLength": 64
                                    },
                                    "NAME": {
                                        "type": "string",
                                        "description": "Name alias used when name is absent."
                                    }
                                },
                                "additionalProperties": true,
                                "description": "PHONE or phone_number is required, including on PATCH. Name is recalculated and custom fields are replaced, not merged. Nonreserved top-level fields become custom_field_values. Reserved keys include PHONE, phone_number, country_code, name, NAME, FIRST_NAME, LAST_NAME, is_subscribed and _token.",
                                "anyOf": [
                                    {
                                        "required": [
                                            "PHONE"
                                        ]
                                    },
                                    {
                                        "required": [
                                            "phone_number"
                                        ]
                                    }
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "PHONE": "255700333444",
                                        "name": "John Updated"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Contact updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Contact",
                                            "description": "The contact record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 66,
                                                "uid": "ctc_01JXYZ001",
                                                "group_id": 8,
                                                "group_uid": "grp_01JXYZABC",
                                                "name": "John Updated",
                                                "country_code": "255",
                                                "phone_number": "700333444",
                                                "full_phone_number": "255700333444",
                                                "is_subscribed": true,
                                                "custom_field_values": []
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Contact or group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Contact not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Validation error.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "PHONE": [
                                                    "The PHONE field is required."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    }
                },
                "x-permission": "contacts.edit",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/contacts/{group_id}/delete/{uid}": {
            "delete": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactsDelete",
                "summary": "Delete a contact",
                "description": "Deletes one contact by uid within a contact group. `DELETE /api/v3/contact-groups/{group}/contacts/{contact}` is the same operation on the REST path.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    },
                    {
                        "$ref": "#/components/parameters/ContactUid"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Contact deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "deleted",
                                                "uid"
                                            ],
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true \u2014 the contact is gone."
                                                },
                                                "uid": {
                                                    "type": "string",
                                                    "description": "The uid of the deleted contact."
                                                }
                                            },
                                            "description": "What was deleted."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "deleted": true,
                                                "uid": "ctc_01JXYZ001"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Contact or group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Contact not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    }
                },
                "x-permission": "contacts.delete",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/contacts/{group_id}/all": {
            "post": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactsList",
                "summary": "List contacts in a group",
                "description": "Lists contacts by group with optional search and pagination controls. `GET /api/v3/contact-groups/{group}/contacts` is the same operation on the REST path.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/GroupId"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "search": {
                                        "type": "string",
                                        "description": "Match contacts whose name or phone number contains this text."
                                    },
                                    "limit": {
                                        "type": "integer",
                                        "description": "Rows per page, 1\u2013100. Defaults to 20."
                                    },
                                    "per_page": {
                                        "type": "integer",
                                        "description": "Alias of `limit`."
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "summary": "Default \u2014 first 25 contacts",
                                    "value": {
                                        "limit": 25
                                    }
                                },
                                "search": {
                                    "summary": "Search by name or phone substring",
                                    "value": {
                                        "search": "Asha",
                                        "limit": 25
                                    }
                                },
                                "page_2": {
                                    "summary": "Pagination \u2014 page 2",
                                    "value": {
                                        "limit": 25,
                                        "page": 2
                                    }
                                },
                                "subscribed_only": {
                                    "summary": "Only subscribed (campaign-eligible) contacts",
                                    "value": {
                                        "is_subscribed": true,
                                        "limit": 50
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Contact collection. Phone numbers are returned in two parts: `country_code` + `phone_number` (local), and a pre-joined `full_phone_number`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items",
                                                "pagination"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Contact",
                                                        "description": "The contact record."
                                                    },
                                                    "description": "The contacts on this page, most recently updated first."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state for this list: where you are and whether more pages follow."
                                                }
                                            },
                                            "description": "A page of contacts and its page state."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "items": [
                                                    {
                                                        "id": 66,
                                                        "uid": "ctc_01JXYZ001",
                                                        "group_id": 8,
                                                        "group_uid": "grp_01JXYZABC",
                                                        "name": "John Doe",
                                                        "country_code": "255",
                                                        "phone_number": "700333444",
                                                        "full_phone_number": "255700333444",
                                                        "is_subscribed": true,
                                                        "custom_field_values": {
                                                            "CITY": "Dar es Salaam"
                                                        }
                                                    }
                                                ],
                                                "pagination": {
                                                    "current_page": 1,
                                                    "per_page": 25,
                                                    "last_page": 1,
                                                    "total": 1,
                                                    "has_more_pages": false
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "404": {
                        "description": "Group not found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Contact group not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    }
                },
                "x-permission": "contacts.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/me": {
            "get": {
                "tags": [
                    "Profile & Balance"
                ],
                "operationId": "v3ProfileMe",
                "summary": "Get current account",
                "description": "Returns the tenant profile represented by the bearer token.",
                "responses": {
                    "200": {
                        "description": "Tenant profile.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "id",
                                                "name",
                                                "slug"
                                            ],
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Tenant id."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Account name as it appears in the dashboard."
                                                },
                                                "slug": {
                                                    "type": "string",
                                                    "description": "URL-safe form of the account name."
                                                },
                                                "external_client_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Your own reference for this account, when one was set. Null otherwise."
                                                },
                                                "created_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "ISO 8601 timestamp of when the account was created."
                                                },
                                                "updated_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "ISO 8601 timestamp of the last change to it."
                                                }
                                            },
                                            "description": "The tenant this token belongs to."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "id": 12,
                                                "name": "Workspace Alpha",
                                                "slug": "workspace-alpha",
                                                "external_client_id": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Invalid API token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/balance": {
            "get": {
                "tags": [
                    "Profile & Balance"
                ],
                "operationId": "v3ProfileBalance",
                "summary": "Get balance",
                "description": "Returns wallet balance, currency, billing mode, and spend metadata.",
                "responses": {
                    "200": {
                        "description": "Tenant wallet balance.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\" on a 2xx response."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "wallet_balance",
                                                "wallet_currency",
                                                "billing_mode"
                                            ],
                                            "properties": {
                                                "wallet_balance": {
                                                    "type": "number",
                                                    "description": "Spendable balance in `wallet_currency`, in major units (973093.57 is TZS 973,093.57)."
                                                },
                                                "wallet_currency": {
                                                    "type": "string",
                                                    "description": "ISO 4217 currency the wallet is held in."
                                                },
                                                "billing_mode": {
                                                    "type": "string",
                                                    "description": "prepaid (sends draw down this balance) or postpaid (sends are invoiced)."
                                                },
                                                "cumulative_spend_cents": {
                                                    "type": "integer",
                                                    "description": "Lifetime spend in cents, which is what moves the account between pricing tiers. Null before the first charge."
                                                },
                                                "tier_override": {
                                                    "type": "boolean",
                                                    "description": "True when an operator pinned this account to a tier instead of letting spend decide it."
                                                },
                                                "last_updated_at": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "ISO 8601 timestamp of the last wallet movement."
                                                }
                                            },
                                            "description": "The wallet behind this account."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "wallet_balance": 12000.5,
                                                "wallet_currency": "TZS",
                                                "billing_mode": "prepaid",
                                                "cumulative_spend_cents": 0,
                                                "tier_override": false
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "Unauthorized.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Missing bearer token."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueList",
                "summary": "List catalogues",
                "description": "Every shop belonging to the token's tenant, newest first, each with its product and order counts.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of catalogues.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items",
                                                "pagination"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Catalogue",
                                                        "description": "The catalogue record."
                                                    },
                                                    "description": "The catalogues on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state for this list: where you are and whether more pages follow."
                                                }
                                            },
                                            "description": "A page of rows and its page state."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 1,
                                                "name": "Acme Duka",
                                                "description": null,
                                                "vertical": "commerce",
                                                "default_currency": "TZS",
                                                "meta_catalogue_id": null,
                                                "is_connected_to_waba": false,
                                                "is_catalogue_visible": false,
                                                "is_cart_enabled": true,
                                                "products_count": 1,
                                                "orders_count": 1,
                                                "last_synced_at": null,
                                                "created_at": "2026-09-04T19:19:55+00:00",
                                                "updated_at": "2026-09-04T19:19:55+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueCreate",
                "summary": "Create a catalogue",
                "description": "Make a shop from your own system, so an integration can finish its setup without anyone opening the dashboard. Connecting the shop to WhatsApp stays a dashboard step: it needs a consent a bearer token cannot give on a person's behalf.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 120,
                                        "description": "Shop name."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 2000,
                                        "description": "What this shop sells."
                                    },
                                    "vertical": {
                                        "type": "string",
                                        "maxLength": 40,
                                        "description": "Commerce vertical, defaults to `commerce`."
                                    },
                                    "default_currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "Currency for products that do not name one."
                                    },
                                    "sku_prefix": {
                                        "type": "string",
                                        "maxLength": 8,
                                        "description": "Prefix for codes the shop issues itself. Accepted on create only."
                                    },
                                    "stock_policy": {
                                        "type": "string",
                                        "enum": [
                                            "external",
                                            "momo"
                                        ],
                                        "description": "Who owns the stock count. Defaults to `external` here."
                                    },
                                    "source_of_truth": {
                                        "type": "string",
                                        "enum": [
                                            "api",
                                            "momo",
                                            "platform"
                                        ],
                                        "description": "Who wins on product fields. Defaults to `api` here."
                                    },
                                    "allow_backorder": {
                                        "type": "boolean",
                                        "description": "Sell past zero."
                                    },
                                    "reservation_ttl_hours": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 720,
                                        "description": "How long a pending order holds stock."
                                    },
                                    "low_stock_threshold": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "minimum": 0,
                                        "description": "Raise `stock.low` at or below this count."
                                    }
                                },
                                "required": [
                                    "name"
                                ]
                            },
                            "example": {
                                "name": "Mango Electronics",
                                "default_currency": "TZS",
                                "sku_prefix": "MNG",
                                "stock_policy": "external"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The created catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Catalogue",
                                            "description": "The catalogue record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 42,
                                        "name": "Mango Electronics",
                                        "description": null,
                                        "vertical": "commerce",
                                        "default_currency": "TZS",
                                        "sku_prefix": "MNG",
                                        "stock_policy": "external",
                                        "source_of_truth": "api",
                                        "allow_backorder": false,
                                        "reservation_ttl_hours": 48,
                                        "low_stock_threshold": null,
                                        "meta_catalogue_id": null,
                                        "is_connected_to_waba": false,
                                        "is_catalogue_visible": false,
                                        "is_cart_enabled": true,
                                        "channels": [
                                            {
                                                "platform": "whatsapp",
                                                "label": "Mango Electronics",
                                                "external_catalogue_id": "1122334455",
                                                "external_account_id": "998877",
                                                "public_slug": null,
                                                "is_connected": true,
                                                "last_synced_at": "2026-09-11T02:00:41+00:00"
                                            }
                                        ],
                                        "products_count": 1994,
                                        "orders_count": 12,
                                        "last_synced_at": "2026-09-11T02:00:41+00:00",
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-11T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueShow",
                "summary": "Read one catalogue",
                "description": "One shop with its product and order counts.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Catalogue",
                                            "description": "The catalogue record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 1,
                                        "name": "Acme Duka",
                                        "description": null,
                                        "vertical": "commerce",
                                        "default_currency": "TZS",
                                        "meta_catalogue_id": null,
                                        "is_connected_to_waba": false,
                                        "is_catalogue_visible": false,
                                        "is_cart_enabled": true,
                                        "products_count": 1,
                                        "orders_count": 1,
                                        "last_synced_at": null,
                                        "created_at": "2026-09-04T19:19:55+00:00",
                                        "updated_at": "2026-09-04T19:19:55+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueUpdate",
                "summary": "Change a catalogue",
                "description": "Change a shop's name, currency or stock policy. `sku_prefix` is ignored: it is stamped into every code the shop has already issued.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 120,
                                        "description": "Shop name."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 2000,
                                        "description": "What this shop sells."
                                    },
                                    "vertical": {
                                        "type": "string",
                                        "maxLength": 40,
                                        "description": "Commerce vertical, defaults to `commerce`."
                                    },
                                    "default_currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "Currency for products that do not name one."
                                    },
                                    "sku_prefix": {
                                        "type": "string",
                                        "maxLength": 8,
                                        "description": "Prefix for codes the shop issues itself. Accepted on create only."
                                    },
                                    "stock_policy": {
                                        "type": "string",
                                        "enum": [
                                            "external",
                                            "momo"
                                        ],
                                        "description": "Who owns the stock count. Defaults to `external` here."
                                    },
                                    "source_of_truth": {
                                        "type": "string",
                                        "enum": [
                                            "api",
                                            "momo",
                                            "platform"
                                        ],
                                        "description": "Who wins on product fields. Defaults to `api` here."
                                    },
                                    "allow_backorder": {
                                        "type": "boolean",
                                        "description": "Sell past zero."
                                    },
                                    "reservation_ttl_hours": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 720,
                                        "description": "How long a pending order holds stock."
                                    },
                                    "low_stock_threshold": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "minimum": 0,
                                        "description": "Raise `stock.low` at or below this count."
                                    }
                                }
                            },
                            "example": {
                                "stock_policy": "momo",
                                "low_stock_threshold": 3
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Catalogue",
                                            "description": "The catalogue record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 42,
                                        "name": "Mango Electronics",
                                        "description": null,
                                        "vertical": "commerce",
                                        "default_currency": "TZS",
                                        "sku_prefix": "MNG",
                                        "stock_policy": "external",
                                        "source_of_truth": "api",
                                        "allow_backorder": false,
                                        "reservation_ttl_hours": 48,
                                        "low_stock_threshold": null,
                                        "meta_catalogue_id": null,
                                        "is_connected_to_waba": false,
                                        "is_catalogue_visible": false,
                                        "is_cart_enabled": true,
                                        "channels": [
                                            {
                                                "platform": "whatsapp",
                                                "label": "Mango Electronics",
                                                "external_catalogue_id": "1122334455",
                                                "external_account_id": "998877",
                                                "public_slug": null,
                                                "is_connected": true,
                                                "last_synced_at": "2026-09-11T02:00:41+00:00"
                                            }
                                        ],
                                        "products_count": 1994,
                                        "orders_count": 12,
                                        "last_synced_at": "2026-09-11T02:00:41+00:00",
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-11T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/products": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueProductList",
                "summary": "List products in a catalogue",
                "description": "Products in the shop, ordered by name. Filter with `search` (name or SKU) and `availability`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "$ref": "#/components/parameters/ProductSearch"
                    },
                    {
                        "$ref": "#/components/parameters/ProductAvailability"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of products.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items",
                                                "pagination"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Product",
                                                        "description": "The product record."
                                                    },
                                                    "description": "The products on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state for this list: where you are and whether more pages follow."
                                                }
                                            },
                                            "description": "A page of rows and its page state."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 1,
                                                "catalogue_id": 1,
                                                "retailer_id": "ACME-001",
                                                "meta_product_id": null,
                                                "name": "Kanga Print",
                                                "description": null,
                                                "url": null,
                                                "price": 25000,
                                                "currency": "TZS",
                                                "sale_price": null,
                                                "image_url": "https://cdn.acme.co.tz/kanga.jpg",
                                                "availability": "in stock",
                                                "condition": "new",
                                                "brand": null,
                                                "category": null,
                                                "product_type": null,
                                                "inventory": null,
                                                "visibility": "published",
                                                "review_status": null,
                                                "last_synced_at": null,
                                                "created_at": "2026-09-04T19:19:55+00:00",
                                                "updated_at": "2026-09-04T19:19:55+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueProductCreate",
                "summary": "Add a product to a catalogue",
                "description": "Add one product. `sku` is optional \u2014 the shop issues `AMY-00042` style codes when you send none. The product is stored first and pushed to every platform the shop is on afterwards, so a 201 means it is saved, and `listings` says where it is live.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "name",
                                    "price"
                                ],
                                "description": "A product. Only a name and a price are required here; an image, a non-zero price and the rest are what individual PLATFORMS require, and a product missing them is stored and reported as `blocked` on that platform rather than refused.",
                                "properties": {
                                    "sku": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Your product code. Left out, the shop issues one."
                                    },
                                    "retailer_id": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "The older name for `sku`."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 200,
                                        "description": "Product name as customers see it."
                                    },
                                    "price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Price in the minor unit of `currency` \u2014 25000 is TZS 250.00 for a 2-decimal currency."
                                    },
                                    "currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "ISO 4217 code. Left out, the shop's own currency is used."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 9000,
                                        "description": "Long description."
                                    },
                                    "sale_price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Optional sale price in the minor unit. Ignored when it is higher than `price`."
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Publicly reachable image. Platforms fetch it themselves, so it cannot sit behind a login."
                                    },
                                    "additional_image_urls": {
                                        "type": "array",
                                        "maxItems": 10,
                                        "items": {
                                            "type": "string",
                                            "format": "uri"
                                        },
                                        "description": "Up to ten more images."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "The product page on your own site."
                                    },
                                    "availability": {
                                        "type": "string",
                                        "enum": [
                                            "in stock",
                                            "out of stock",
                                            "preorder",
                                            "available for order",
                                            "discontinued"
                                        ],
                                        "description": "Left out, it is derived from `inventory`: a count of zero means `out of stock` unless the shop allows backorders. Sent explicitly, what you send wins."
                                    },
                                    "condition": {
                                        "type": "string",
                                        "enum": [
                                            "new",
                                            "refurbished",
                                            "used"
                                        ],
                                        "description": "Item condition."
                                    },
                                    "brand": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Brand name. Becomes a brand record on first use."
                                    },
                                    "category": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Category name. Becomes a category record on first use."
                                    },
                                    "product_type": {
                                        "type": "string",
                                        "maxLength": 750,
                                        "description": "Your own taxonomy path."
                                    },
                                    "inventory": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Units on hand."
                                    },
                                    "visibility": {
                                        "type": "string",
                                        "enum": [
                                            "staging",
                                            "published"
                                        ],
                                        "description": "Whether customers may see it."
                                    },
                                    "custom_labels": {
                                        "type": "array",
                                        "maxItems": 5,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Up to five free labels for your own segmentation."
                                    }
                                }
                            },
                            "example": {
                                "sku": "MNG-45W",
                                "name": "Charger Mango 45W",
                                "price": 4500000,
                                "currency": "TZS",
                                "image_url": "https://cdn.example.com/mng45.jpg",
                                "inventory": 12
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The created product.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Product",
                                            "description": "The product record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 2,
                                        "catalogue_id": 1,
                                        "retailer_id": "ACME-002",
                                        "meta_product_id": null,
                                        "name": "Kitenge 6 yards",
                                        "description": "Wax print, 6 yards.",
                                        "url": null,
                                        "price": 45000,
                                        "currency": "TZS",
                                        "sale_price": null,
                                        "image_url": "https://cdn.acme.co.tz/kitenge.jpg",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": null,
                                        "category": null,
                                        "product_type": null,
                                        "inventory": null,
                                        "visibility": "published",
                                        "review_status": null,
                                        "last_synced_at": null,
                                        "created_at": "2026-09-04T19:19:55+00:00",
                                        "updated_at": "2026-09-04T19:19:55+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "Validation failed, or the `retailer_id` is already used in this catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "missing_fields": {
                                        "summary": "Required fields missing",
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "retailer_id": [
                                                    "The retailer id field is required."
                                                ],
                                                "price": [
                                                    "The price field is required."
                                                ],
                                                "currency": [
                                                    "The currency field is required."
                                                ],
                                                "image_url": [
                                                    "The image url field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "duplicate_sku": {
                                        "summary": "Duplicate retailer_id",
                                        "value": {
                                            "status": "error",
                                            "message": "Retailer ID already exists in this catalogue.",
                                            "errors": {
                                                "retailer_id": [
                                                    "This retailer_id is already used by another product in this catalogue."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "$ref": "#/components/responses/UpstreamFailure"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/products/batch": {
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueProductBatch",
                "summary": "Sync products in bulk",
                "description": "The endpoint a store integration lives on. Send up to 5,000 products; every field in the product schema is stored, not just the identity ones. The call returns **202** with a sync id and the work happens in the background, because pushing a catalogue to a platform takes longer than an HTTP request should.\n\nRead the outcome from `GET /catalogues/{catalogue}/syncs/{sync}`: it names every row that was refused and every product a platform will not show, with the reason for each.\n\nSend an `Idempotency-Key` header on scheduled runs. A repeat of the same key returns the run that already owns it with `replayed: true` and imports nothing, so a cron that times out is safe to retry.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "maxLength": 190,
                            "example": "nightly-2026-09-11"
                        },
                        "description": "Your own name for this run, for example `nightly-2026-09-11`. Repeating it never imports twice."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "products"
                                ],
                                "properties": {
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "upsert",
                                            "replace"
                                        ],
                                        "default": "upsert",
                                        "description": "`upsert` leaves products the payload does not mention alone. `replace` says this payload IS the catalogue and retires everything missing from it \u2014 use it only when you are sending your whole product list."
                                    },
                                    "products": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 5000,
                                        "items": {
                                            "type": "object",
                                            "required": [
                                                "name",
                                                "price"
                                            ],
                                            "description": "A product. Only a name and a price are required here; an image, a non-zero price and the rest are what individual PLATFORMS require, and a product missing them is stored and reported as `blocked` on that platform rather than refused.",
                                            "properties": {
                                                "sku": {
                                                    "type": "string",
                                                    "maxLength": 100,
                                                    "description": "Your product code. Left out, the shop issues one."
                                                },
                                                "retailer_id": {
                                                    "type": "string",
                                                    "maxLength": 100,
                                                    "description": "The older name for `sku`."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "maxLength": 200,
                                                    "description": "Product name as customers see it."
                                                },
                                                "price": {
                                                    "type": "integer",
                                                    "minimum": 0,
                                                    "description": "Price in the minor unit of `currency` \u2014 25000 is TZS 250.00 for a 2-decimal currency."
                                                },
                                                "currency": {
                                                    "type": "string",
                                                    "minLength": 3,
                                                    "maxLength": 3,
                                                    "description": "ISO 4217 code. Left out, the shop's own currency is used."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "maxLength": 9000,
                                                    "description": "Long description."
                                                },
                                                "sale_price": {
                                                    "type": "integer",
                                                    "minimum": 0,
                                                    "description": "Optional sale price in the minor unit. Ignored when it is higher than `price`."
                                                },
                                                "image_url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "maxLength": 2048,
                                                    "description": "Publicly reachable image. Platforms fetch it themselves, so it cannot sit behind a login."
                                                },
                                                "additional_image_urls": {
                                                    "type": "array",
                                                    "maxItems": 10,
                                                    "items": {
                                                        "type": "string",
                                                        "format": "uri"
                                                    },
                                                    "description": "Up to ten more images."
                                                },
                                                "url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "maxLength": 2048,
                                                    "description": "The product page on your own site."
                                                },
                                                "availability": {
                                                    "type": "string",
                                                    "enum": [
                                                        "in stock",
                                                        "out of stock",
                                                        "preorder",
                                                        "available for order",
                                                        "discontinued"
                                                    ],
                                                    "description": "Left out, it is derived from `inventory`: a count of zero means `out of stock` unless the shop allows backorders. Sent explicitly, what you send wins."
                                                },
                                                "condition": {
                                                    "type": "string",
                                                    "enum": [
                                                        "new",
                                                        "refurbished",
                                                        "used"
                                                    ],
                                                    "description": "Item condition."
                                                },
                                                "brand": {
                                                    "type": "string",
                                                    "maxLength": 255,
                                                    "description": "Brand name. Becomes a brand record on first use."
                                                },
                                                "category": {
                                                    "type": "string",
                                                    "maxLength": 255,
                                                    "description": "Category name. Becomes a category record on first use."
                                                },
                                                "product_type": {
                                                    "type": "string",
                                                    "maxLength": 750,
                                                    "description": "Your own taxonomy path."
                                                },
                                                "inventory": {
                                                    "type": "integer",
                                                    "minimum": 0,
                                                    "description": "Units on hand."
                                                },
                                                "visibility": {
                                                    "type": "string",
                                                    "enum": [
                                                        "staging",
                                                        "published"
                                                    ],
                                                    "description": "Whether customers may see it."
                                                },
                                                "custom_labels": {
                                                    "type": "array",
                                                    "maxItems": 5,
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Up to five free labels for your own segmentation."
                                                }
                                            }
                                        },
                                        "description": "The products. A row that cannot be stored is reported in the sync report as one rejected row; it does not refuse the rest of the file."
                                    }
                                }
                            },
                            "example": {
                                "mode": "upsert",
                                "products": [
                                    {
                                        "sku": "MNG-45W",
                                        "name": "Charger Mango 45W",
                                        "description": "USB-C PD, 1 m cable",
                                        "price": 4500000,
                                        "currency": "TZS",
                                        "sale_price": 3900000,
                                        "image_url": "https://cdn.example.com/mng45.jpg",
                                        "inventory": 12,
                                        "availability": "in stock",
                                        "brand": "Mango",
                                        "category": "Chargers"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "The sync was accepted. Poll it for the outcome.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatalogueSync",
                                            "description": "The sync that was accepted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 812,
                                        "catalogue_id": 42,
                                        "source": "api",
                                        "mode": "upsert",
                                        "status": "queued",
                                        "idempotency_key": "nightly-2026-09-11",
                                        "received": 2000,
                                        "created": 0,
                                        "updated": 0,
                                        "unchanged": 0,
                                        "rejected": 0,
                                        "retired": 0,
                                        "platforms": {
                                            "whatsapp": {
                                                "pending": 0
                                            }
                                        },
                                        "problems": [],
                                        "problems_truncated": false,
                                        "error": null,
                                        "started_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-09-11T02:00:04+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/products/{product}": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueProductShow",
                "summary": "Read one product",
                "description": "One product from a catalogue. A product that exists but sits in a different catalogue answers `404`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "$ref": "#/components/parameters/ProductId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The product.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Product",
                                            "description": "The product record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 1,
                                        "catalogue_id": 1,
                                        "retailer_id": "ACME-001",
                                        "meta_product_id": null,
                                        "name": "Kanga Print",
                                        "description": null,
                                        "url": null,
                                        "price": 25000,
                                        "currency": "TZS",
                                        "sale_price": null,
                                        "image_url": "https://cdn.acme.co.tz/kanga.jpg",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": null,
                                        "category": null,
                                        "product_type": null,
                                        "inventory": null,
                                        "visibility": "published",
                                        "review_status": null,
                                        "last_synced_at": null,
                                        "created_at": "2026-09-04T19:19:55+00:00",
                                        "updated_at": "2026-09-04T19:19:55+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "put": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueProductUpdate",
                "summary": "Update a product",
                "description": "Change one product. Only the fields you send are touched, so sending `{\"inventory\": 0}` is a stock update and nothing else. The product code cannot be changed here \u2014 it is the identity platforms know the item by.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "$ref": "#/components/parameters/ProductId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [],
                                "description": "A product. Only a name and a price are required here; an image, a non-zero price and the rest are what individual PLATFORMS require, and a product missing them is stored and reported as `blocked` on that platform rather than refused.",
                                "properties": {
                                    "sku": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Your product code. Left out, the shop issues one."
                                    },
                                    "retailer_id": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "The older name for `sku`."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 200,
                                        "description": "Product name as customers see it."
                                    },
                                    "price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Price in the minor unit of `currency` \u2014 25000 is TZS 250.00 for a 2-decimal currency."
                                    },
                                    "currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "ISO 4217 code. Left out, the shop's own currency is used."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 9000,
                                        "description": "Long description."
                                    },
                                    "sale_price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Optional sale price in the minor unit. Ignored when it is higher than `price`."
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Publicly reachable image. Platforms fetch it themselves, so it cannot sit behind a login."
                                    },
                                    "additional_image_urls": {
                                        "type": "array",
                                        "maxItems": 10,
                                        "items": {
                                            "type": "string",
                                            "format": "uri"
                                        },
                                        "description": "Up to ten more images."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "The product page on your own site."
                                    },
                                    "availability": {
                                        "type": "string",
                                        "enum": [
                                            "in stock",
                                            "out of stock",
                                            "preorder",
                                            "available for order",
                                            "discontinued"
                                        ],
                                        "description": "Left out, it is derived from `inventory`: a count of zero means `out of stock` unless the shop allows backorders. Sent explicitly, what you send wins."
                                    },
                                    "condition": {
                                        "type": "string",
                                        "enum": [
                                            "new",
                                            "refurbished",
                                            "used"
                                        ],
                                        "description": "Item condition."
                                    },
                                    "brand": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Brand name. Becomes a brand record on first use."
                                    },
                                    "category": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Category name. Becomes a category record on first use."
                                    },
                                    "product_type": {
                                        "type": "string",
                                        "maxLength": 750,
                                        "description": "Your own taxonomy path."
                                    },
                                    "inventory": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Units on hand."
                                    },
                                    "visibility": {
                                        "type": "string",
                                        "enum": [
                                            "staging",
                                            "published"
                                        ],
                                        "description": "Whether customers may see it."
                                    },
                                    "custom_labels": {
                                        "type": "array",
                                        "maxItems": 5,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Up to five free labels for your own segmentation."
                                    }
                                }
                            },
                            "example": {
                                "price": 4200000,
                                "inventory": 7
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated product.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Product",
                                            "description": "The product record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 1,
                                        "catalogue_id": 1,
                                        "retailer_id": "ACME-001",
                                        "meta_product_id": null,
                                        "name": "Kanga Print",
                                        "description": null,
                                        "url": null,
                                        "price": 27000,
                                        "currency": "TZS",
                                        "sale_price": null,
                                        "image_url": "https://cdn.acme.co.tz/kanga.jpg",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": null,
                                        "category": null,
                                        "product_type": null,
                                        "inventory": null,
                                        "visibility": "published",
                                        "review_status": null,
                                        "last_synced_at": null,
                                        "created_at": "2026-09-04T19:19:55+00:00",
                                        "updated_at": "2026-09-04T19:19:55+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "$ref": "#/components/responses/UpstreamFailure"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueProductDelete",
                "summary": "Delete a product",
                "description": "Removes the product from the catalogue, and from Meta first when it was mirrored there.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "$ref": "#/components/parameters/ProductId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The product was deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "deleted",
                                                "id"
                                            ],
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                },
                                                "id": {
                                                    "type": "integer",
                                                    "description": "Id of the deleted product."
                                                },
                                                "retailer_id": {
                                                    "type": "string",
                                                    "description": "SKU of the deleted product, free to reuse now."
                                                }
                                            },
                                            "description": "What was deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "deleted": true,
                                        "id": 1,
                                        "retailer_id": "ACME-001"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/orders": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueOrderList",
                "summary": "List orders",
                "description": "Orders customers submitted from a WhatsApp cart, newest first. Filter by `status`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OrderStatusFilter"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/PerPage"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    },
                    {
                        "name": "updated_since",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2026-09-11T02:00:00+00:00"
                        },
                        "description": "Only orders changed at or after this moment, newest change first. This is how you recover from a webhook you missed."
                    },
                    {
                        "name": "platform",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "whatsapp"
                        },
                        "description": "Only orders that arrived through this platform."
                    },
                    {
                        "name": "catalogue_id",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "example": 42
                        },
                        "description": "Only orders against this shop."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of orders.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items",
                                                "pagination"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Order",
                                                        "description": "The order record."
                                                    },
                                                    "description": "The orders on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state for this list: where you are and whether more pages follow."
                                                }
                                            },
                                            "description": "A page of rows and its page state."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 1,
                                                "catalogue_id": 1,
                                                "catalogue": {
                                                    "id": 1,
                                                    "name": "Acme Duka"
                                                },
                                                "customer_wa_id": "255700111222",
                                                "customer_name": "Asha Mrisho",
                                                "customer_phone": null,
                                                "customer_note": null,
                                                "product_items": [
                                                    {
                                                        "product_retailer_id": "ACME-001",
                                                        "quantity": 2,
                                                        "item_price": 25000,
                                                        "currency": "TZS"
                                                    }
                                                ],
                                                "total_amount": 50000,
                                                "total_currency": "TZS",
                                                "status": "pending",
                                                "gateway_message_id": null,
                                                "created_at": "2026-09-04T19:19:55+00:00",
                                                "updated_at": "2026-09-04T19:19:55+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/orders/{order}": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueOrderShow",
                "summary": "Read one order",
                "description": "One order with its cart lines and the catalogue it came from.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OrderId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Order",
                                            "description": "The order record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 1,
                                        "catalogue_id": 1,
                                        "catalogue": {
                                            "id": 1,
                                            "name": "Acme Duka"
                                        },
                                        "customer_wa_id": "255700111222",
                                        "customer_name": "Asha Mrisho",
                                        "customer_phone": null,
                                        "customer_note": null,
                                        "product_items": [
                                            {
                                                "product_retailer_id": "ACME-001",
                                                "quantity": 2,
                                                "item_price": 25000,
                                                "currency": "TZS"
                                            }
                                        ],
                                        "total_amount": 50000,
                                        "total_currency": "TZS",
                                        "status": "pending",
                                        "gateway_message_id": null,
                                        "created_at": "2026-09-04T19:19:55+00:00",
                                        "updated_at": "2026-09-04T19:19:55+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/orders/{order}/status": {
            "put": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueOrderStatusUpdate",
                "summary": "Move an order to another status",
                "description": "Records a fulfilment transition. Each move is appended to the order history, and when the shop has status templates configured the customer is notified on WhatsApp.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OrderId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "status"
                                ],
                                "properties": {
                                    "status": {
                                        "type": "string",
                                        "enum": [
                                            "pending",
                                            "confirmed",
                                            "processing",
                                            "shipped",
                                            "delivered",
                                            "cancelled",
                                            "refunded"
                                        ],
                                        "description": "The status to move to."
                                    }
                                }
                            },
                            "examples": {
                                "confirm": {
                                    "summary": "Confirm a new order",
                                    "value": {
                                        "status": "confirmed"
                                    }
                                },
                                "ship": {
                                    "summary": "Mark shipped",
                                    "value": {
                                        "status": "shipped"
                                    }
                                },
                                "cancel": {
                                    "summary": "Cancel",
                                    "value": {
                                        "status": "cancelled"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The order in its new status.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Order",
                                            "description": "The order record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 1,
                                        "catalogue_id": 1,
                                        "catalogue": {
                                            "id": 1,
                                            "name": "Acme Duka"
                                        },
                                        "customer_wa_id": "255700111222",
                                        "customer_name": "Asha Mrisho",
                                        "customer_phone": null,
                                        "customer_note": null,
                                        "product_items": [
                                            {
                                                "product_retailer_id": "ACME-001",
                                                "quantity": 2,
                                                "item_price": 25000,
                                                "currency": "TZS"
                                            }
                                        ],
                                        "total_amount": 50000,
                                        "total_currency": "TZS",
                                        "status": "confirmed",
                                        "gateway_message_id": null,
                                        "created_at": "2026-09-04T19:19:55+00:00",
                                        "updated_at": "2026-09-04T19:19:55+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "description": "Unknown status value.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Validation failed.",
                                    "errors": {
                                        "status": [
                                            "The selected status is invalid."
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/send-product": {
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueSendProduct",
                "summary": "Send one product into a chat, on any platform",
                "description": "With `platform: whatsapp` (the default) this is Meta's interactive product message: the customer sees a card and can add to cart. It needs `to`, the provider `catalogue_id` and `product_retailer_id`.\n\nWith any other platform the honest answer is a **link**. The response carries the product's address on that platform and the endpoint to send it with \u2014 one send path for every platform, rather than one per platform. A product that is not published there, or a platform with nowhere to point at, is refused with a 422 that says so.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "product_retailer_id"
                                ],
                                "properties": {
                                    "platform": {
                                        "type": "string",
                                        "enum": [
                                            "whatsapp",
                                            "storefront",
                                            "facebook",
                                            "instagram",
                                            "tiktok"
                                        ],
                                        "default": "whatsapp",
                                        "description": "Where the product should be shown. Defaults to WhatsApp."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Customer's WhatsApp number in E.164 without +. Required on WhatsApp only."
                                    },
                                    "catalogue_id": {
                                        "type": "string",
                                        "description": "Meta catalogue id of the connected shop. Required on WhatsApp only."
                                    },
                                    "product_retailer_id": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "SKU of the product to show."
                                    },
                                    "body": {
                                        "type": "string",
                                        "maxLength": 1024,
                                        "description": "Message text above the product card."
                                    },
                                    "footer": {
                                        "type": "string",
                                        "maxLength": 60,
                                        "description": "Small footer text."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Send from this WhatsApp number when the tenant has several. Defaults to the account default. `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself)."
                                    }
                                }
                            },
                            "example": {
                                "to": "255700111222",
                                "catalogue_id": "1234567890",
                                "product_retailer_id": "ACME-001",
                                "body": "Here is the kanga you asked about.",
                                "footer": "Acme Duka"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "On WhatsApp, the gateway message id. On any other platform, the link to send.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "oneOf": [
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "message_id": {
                                                            "type": "string",
                                                            "description": "The gateway message id, on WhatsApp."
                                                        }
                                                    }
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "platform": {
                                                            "type": "string",
                                                            "description": "The platform asked for."
                                                        },
                                                        "sku": {
                                                            "type": "string",
                                                            "description": "The product code."
                                                        },
                                                        "link": {
                                                            "type": "string",
                                                            "format": "uri",
                                                            "description": "Where the product lives on that platform."
                                                        },
                                                        "state": {
                                                            "type": "string",
                                                            "description": "The listing state there."
                                                        },
                                                        "send_with": {
                                                            "type": "string",
                                                            "description": "The endpoint to send the link with."
                                                        }
                                                    }
                                                }
                                            ],
                                            "description": "A message id on WhatsApp; a link everywhere else."
                                        }
                                    }
                                },
                                "examples": {
                                    "whatsapp": {
                                        "summary": "Sent as an interactive message",
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "message_id": "wamid.HBgL\u2026"
                                            }
                                        }
                                    },
                                    "storefront": {
                                        "summary": "A link to send",
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "platform": "storefront",
                                                "sku": "MNG-45W",
                                                "link": "https://business.momo.tz/shop/mango/p/MNG-45W",
                                                "state": "synced",
                                                "send_with": "/api/v3/whatsapp/send"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "422": {
                        "description": "Validation failed, or the tenant has no active WhatsApp channel.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "no_channel": {
                                        "summary": "No WhatsApp channel connected",
                                        "value": {
                                            "status": "error",
                                            "message": "No WhatsApp channel configured."
                                        }
                                    },
                                    "validation": {
                                        "summary": "Missing fields",
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "to": [
                                                    "The to field is required."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "$ref": "#/components/responses/UpstreamFailure"
                    }
                }
            }
        },
        "/api/v3/catalogues/send-product-list": {
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueSendProductList",
                "summary": "Send a multi-product list to a customer",
                "description": "Sends a multi-product message: up to 10 sections of products the customer can browse and add to a cart.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "to",
                                    "catalogue_id",
                                    "header_text",
                                    "body",
                                    "sections"
                                ],
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "description": "Customer's WhatsApp number in E.164 without +."
                                    },
                                    "catalogue_id": {
                                        "type": "string",
                                        "description": "Meta catalogue id of the connected shop."
                                    },
                                    "header_text": {
                                        "type": "string",
                                        "maxLength": 60,
                                        "description": "Bold header above the list."
                                    },
                                    "body": {
                                        "type": "string",
                                        "maxLength": 1024,
                                        "description": "Message text."
                                    },
                                    "footer": {
                                        "type": "string",
                                        "maxLength": 60,
                                        "description": "Small footer text."
                                    },
                                    "sections": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 10,
                                        "description": "Product groups, in display order.",
                                        "items": {
                                            "type": "object",
                                            "required": [
                                                "title",
                                                "product_items"
                                            ],
                                            "properties": {
                                                "title": {
                                                    "type": "string",
                                                    "maxLength": 24,
                                                    "description": "Section heading."
                                                },
                                                "product_items": {
                                                    "type": "array",
                                                    "minItems": 1,
                                                    "description": "Products in the section.",
                                                    "items": {
                                                        "type": "object",
                                                        "required": [
                                                            "product_retailer_id"
                                                        ],
                                                        "properties": {
                                                            "product_retailer_id": {
                                                                "type": "string",
                                                                "maxLength": 100,
                                                                "description": "SKU to include."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Send from this WhatsApp number when the tenant has several. `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself)."
                                    }
                                }
                            },
                            "example": {
                                "to": "255700111222",
                                "catalogue_id": "1234567890",
                                "header_text": "New this week",
                                "body": "Pick what you like and add it to your cart.",
                                "footer": "Acme Duka",
                                "sections": [
                                    {
                                        "title": "Kanga",
                                        "product_items": [
                                            {
                                                "product_retailer_id": "ACME-001"
                                            },
                                            {
                                                "product_retailer_id": "ACME-002"
                                            }
                                        ]
                                    },
                                    {
                                        "title": "Vitenge",
                                        "product_items": [
                                            {
                                                "product_retailer_id": "ACME-101"
                                            }
                                        ]
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "WhatsApp accepted the message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "message_id"
                                            ],
                                            "properties": {
                                                "message_id": {
                                                    "type": "string",
                                                    "description": "The WhatsApp message id (`wamid.\u2026`) to match against later message.* webhooks."
                                                }
                                            },
                                            "description": "The message WhatsApp accepted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "message_id": "wamid.HBgLMjU1NzAwMTExMjIyFQIAERgSN0YzNzhBQTQ5MzBBM0YwQzE2AA=="
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "422": {
                        "description": "Validation failed, or the tenant has no active WhatsApp channel.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "no_channel": {
                                        "summary": "No WhatsApp channel connected",
                                        "value": {
                                            "status": "error",
                                            "message": "No WhatsApp channel configured."
                                        }
                                    },
                                    "validation": {
                                        "summary": "Missing fields",
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "to": [
                                                    "The to field is required."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "$ref": "#/components/responses/UpstreamFailure"
                    }
                }
            }
        },
        "/api/v3/catalogues/send-catalogue": {
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueSendCatalogue",
                "summary": "Send the whole catalogue to a customer",
                "description": "Sends a catalogue message: an invitation to browse the full shop, optionally showing one product as the thumbnail.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "to",
                                    "body"
                                ],
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "description": "Customer's WhatsApp number in E.164 without +."
                                    },
                                    "body": {
                                        "type": "string",
                                        "maxLength": 1024,
                                        "description": "Message text."
                                    },
                                    "thumbnail_product_retailer_id": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "SKU to use as the cover image. Defaults to the first product."
                                    },
                                    "footer": {
                                        "type": "string",
                                        "maxLength": 60,
                                        "description": "Small footer text."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "Send from this WhatsApp number when the tenant has several. `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself)."
                                    }
                                }
                            },
                            "example": {
                                "to": "255700111222",
                                "body": "Karibu! Browse our full catalogue here.",
                                "thumbnail_product_retailer_id": "ACME-001",
                                "footer": "Acme Duka"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "WhatsApp accepted the message.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "message_id"
                                            ],
                                            "properties": {
                                                "message_id": {
                                                    "type": "string",
                                                    "description": "The WhatsApp message id (`wamid.\u2026`) to match against later message.* webhooks."
                                                }
                                            },
                                            "description": "The message WhatsApp accepted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "message_id": "wamid.HBgLMjU1NzAwMTExMjIyFQIAERgSN0YzNzhBQTQ5MzBBM0YwQzE2AA=="
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "422": {
                        "description": "Validation failed, or the tenant has no active WhatsApp channel.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "no_channel": {
                                        "summary": "No WhatsApp channel connected",
                                        "value": {
                                            "status": "error",
                                            "message": "No WhatsApp channel configured."
                                        }
                                    },
                                    "validation": {
                                        "summary": "Missing fields",
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "to": [
                                                    "The to field is required."
                                                ]
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "$ref": "#/components/responses/UpstreamFailure"
                    }
                }
            }
        },
        "/api/v3/data/tables": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataTablesList",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "List data tables",
                "description": "Every table this tenant has defined, by name. Take the `id` into the other endpoints; the schema endpoint tells you what each table holds.",
                "responses": {
                    "200": {
                        "description": "The tables.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "tables"
                                    ],
                                    "properties": {
                                        "tables": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/DataTable"
                                            },
                                            "description": "The tables, ordered by name."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "tables": [
                                                {
                                                    "id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                    "name": "Customers",
                                                    "slug": "customers",
                                                    "description": "Everyone who has bought from us.",
                                                    "icon": "users",
                                                    "records_count": 1286,
                                                    "columns_count": 6,
                                                    "updated_at": "2026-09-07T14:02:31+00:00"
                                                },
                                                {
                                                    "id": "4e8d9c0b-1a2f-4b3c-8d4e-5f6a7b8c9d0e",
                                                    "name": "Deliveries",
                                                    "slug": "deliveries",
                                                    "description": null,
                                                    "icon": null,
                                                    "records_count": 52014,
                                                    "columns_count": 9,
                                                    "updated_at": "2026-09-08T06:15:00+00:00"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/tables/{table}/schema": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataTableSchema",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "Read a table's schema",
                "description": "The columns of a table \u2014 key, type, whether required or unique, the validation rules a write runs and the operators a filter may use \u2014 plus what every type can do, the system columns, quota usage and what this key is allowed to do. Read it once before writing records, and again after a column changes in the dashboard.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The schema.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataSchema"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "table": {
                                                "id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                "name": "Customers",
                                                "slug": "customers",
                                                "description": "Everyone who has bought from us.",
                                                "icon": "users",
                                                "records_count": 1286,
                                                "storage_bytes": 418304,
                                                "title_column": "name",
                                                "created_at": "2026-08-30T09:00:00+00:00",
                                                "updated_at": "2026-09-07T14:02:31+00:00"
                                            },
                                            "columns": [
                                                {
                                                    "id": "6a1b2c3d-0000-4000-8000-000000000001",
                                                    "key": "name",
                                                    "label": "Name",
                                                    "type": "text",
                                                    "position": 0,
                                                    "required": true,
                                                    "unique": false,
                                                    "indexed": false,
                                                    "index_status": null,
                                                    "index_error": null,
                                                    "config": {
                                                        "ui": {
                                                            "is_title_field": true
                                                        }
                                                    },
                                                    "rules": [
                                                        "required",
                                                        "string",
                                                        "max:255"
                                                    ],
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "contains",
                                                        "starts_with",
                                                        "is_empty",
                                                        "is_not_empty",
                                                        "in"
                                                    ],
                                                    "ui": {
                                                        "is_title_field": true,
                                                        "cell": "text",
                                                        "input": "text",
                                                        "filter": "text",
                                                        "width": 200
                                                    }
                                                },
                                                {
                                                    "id": "6a1b2c3d-0000-4000-8000-000000000002",
                                                    "key": "phone",
                                                    "label": "Simu",
                                                    "type": "phone",
                                                    "position": 1,
                                                    "required": true,
                                                    "unique": true,
                                                    "indexed": true,
                                                    "index_status": "ready",
                                                    "index_error": null,
                                                    "config": {
                                                        "region": "TZ"
                                                    },
                                                    "rules": [
                                                        "required",
                                                        "phone:TZ"
                                                    ],
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "starts_with",
                                                        "contains",
                                                        "is_empty",
                                                        "is_not_empty",
                                                        "in"
                                                    ],
                                                    "ui": {
                                                        "cell": "phone",
                                                        "input": "phone",
                                                        "filter": "text",
                                                        "width": 160
                                                    }
                                                },
                                                {
                                                    "id": "6a1b2c3d-0000-4000-8000-000000000003",
                                                    "key": "region",
                                                    "label": "Region",
                                                    "type": "select",
                                                    "position": 2,
                                                    "required": false,
                                                    "unique": false,
                                                    "indexed": false,
                                                    "index_status": null,
                                                    "index_error": null,
                                                    "config": {
                                                        "options": [
                                                            {
                                                                "key": "dar",
                                                                "label": "Dar es Salaam"
                                                            },
                                                            {
                                                                "key": "arusha",
                                                                "label": "Arusha"
                                                            }
                                                        ]
                                                    },
                                                    "rules": [
                                                        "in:dar,arusha"
                                                    ],
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "is_empty",
                                                        "is_not_empty",
                                                        "in"
                                                    ],
                                                    "ui": {
                                                        "cell": "select",
                                                        "input": "select",
                                                        "filter": "select",
                                                        "width": 140
                                                    }
                                                },
                                                {
                                                    "id": "6a1b2c3d-0000-4000-8000-000000000004",
                                                    "key": "opt_in",
                                                    "label": "Opted in",
                                                    "type": "boolean",
                                                    "position": 3,
                                                    "required": false,
                                                    "unique": false,
                                                    "indexed": false,
                                                    "index_status": null,
                                                    "index_error": null,
                                                    "config": [],
                                                    "rules": [
                                                        "boolean"
                                                    ],
                                                    "operators": [
                                                        "equals",
                                                        "is_empty",
                                                        "is_not_empty"
                                                    ],
                                                    "ui": {
                                                        "cell": "boolean",
                                                        "input": "checkbox",
                                                        "filter": "boolean",
                                                        "width": 100
                                                    }
                                                },
                                                {
                                                    "id": "6a1b2c3d-0000-4000-8000-000000000005",
                                                    "key": "balance",
                                                    "label": "Balance",
                                                    "type": "currency",
                                                    "position": 4,
                                                    "required": false,
                                                    "unique": false,
                                                    "indexed": false,
                                                    "index_status": null,
                                                    "index_error": null,
                                                    "config": {
                                                        "currency": "TZS"
                                                    },
                                                    "rules": [
                                                        "numeric"
                                                    ],
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "greater_than",
                                                        "less_than",
                                                        "between",
                                                        "is_empty",
                                                        "is_not_empty"
                                                    ],
                                                    "ui": {
                                                        "cell": "currency",
                                                        "input": "number",
                                                        "filter": "number",
                                                        "width": 140
                                                    }
                                                }
                                            ],
                                            "types": {
                                                "text": {
                                                    "label": "Text",
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "contains",
                                                        "starts_with",
                                                        "is_empty",
                                                        "is_not_empty",
                                                        "in"
                                                    ],
                                                    "ui": {
                                                        "cell": "text",
                                                        "input": "text",
                                                        "filter": "text",
                                                        "width": 200
                                                    },
                                                    "numeric": false,
                                                    "temporal": false
                                                },
                                                "phone": {
                                                    "label": "Phone",
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "starts_with",
                                                        "contains",
                                                        "is_empty",
                                                        "is_not_empty",
                                                        "in"
                                                    ],
                                                    "ui": {
                                                        "cell": "phone",
                                                        "input": "phone",
                                                        "filter": "text",
                                                        "width": 160
                                                    },
                                                    "numeric": false,
                                                    "temporal": false
                                                },
                                                "datetime": {
                                                    "label": "Date & time",
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "greater_than",
                                                        "less_than",
                                                        "between",
                                                        "is_empty",
                                                        "is_not_empty"
                                                    ],
                                                    "ui": {
                                                        "cell": "datetime",
                                                        "input": "datetime",
                                                        "filter": "date",
                                                        "width": 180
                                                    },
                                                    "numeric": false,
                                                    "temporal": true
                                                }
                                            },
                                            "system_columns": [
                                                {
                                                    "key": "$id",
                                                    "label": "ID",
                                                    "type": "relation",
                                                    "operators": [
                                                        "equals",
                                                        "in"
                                                    ]
                                                },
                                                {
                                                    "key": "$created_at",
                                                    "label": "Created",
                                                    "type": "datetime",
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "greater_than",
                                                        "less_than",
                                                        "between"
                                                    ]
                                                },
                                                {
                                                    "key": "$updated_at",
                                                    "label": "Updated",
                                                    "type": "datetime",
                                                    "operators": [
                                                        "equals",
                                                        "not_equals",
                                                        "greater_than",
                                                        "less_than",
                                                        "between"
                                                    ]
                                                },
                                                {
                                                    "key": "$source",
                                                    "label": "Source",
                                                    "type": "text",
                                                    "operators": [
                                                        "equals",
                                                        "in",
                                                        "starts_with"
                                                    ]
                                                }
                                            ],
                                            "limits": {
                                                "columns": {
                                                    "used": 5,
                                                    "max": 40
                                                },
                                                "indexes": {
                                                    "used": 1,
                                                    "max": 5
                                                },
                                                "records": {
                                                    "used": 1286,
                                                    "max": 500000
                                                },
                                                "storage": {
                                                    "used_bytes": 418304,
                                                    "max_bytes": 2147483648
                                                }
                                            },
                                            "sort_index_threshold": 20000,
                                            "can": {
                                                "manage": true,
                                                "edit_records": true,
                                                "manage_reports": true
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No table with that id for this tenant (or the id is not a UUID).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/tables/{table}/records": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataRecordsList",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "List records",
                "description": "Returns a keyset page, default limit 50 and maximum 200, with optional JSON condition-tree filter and q text search. Preserve filter/q/sort/dir when sending next_cursor back as cursor. Invalid cursor text restarts at page one. Count is null unless with_count is enabled. At or above sort_index_threshold, user-column sorts need an index; unsupported sorts/operators return 501 not_supported.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    },
                    {
                        "name": "filter",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "URL-encoded JSON condition tree, with all/any groups or column/op/value leaves. Malformed filters/unknown columns return 422; unsupported field operators return 501.",
                        "example": "{\"all\":[{\"column\":\"opt_in\",\"op\":\"equals\",\"value\":true},{\"any\":[{\"column\":\"region\",\"op\":\"in\",\"value\":[\"dar\",\"arusha\"]},{\"column\":\"$created_at\",\"op\":\"greater_than\",\"value\":{\"relative\":\"last_7_days\"}}]}]}"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Free-text search, case-insensitive, over up to six text-like columns (text, long_text, phone, email). Ignored on a table with none.",
                        "example": "asha"
                    },
                    {
                        "name": "sort",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "$created_at"
                        },
                        "description": "Column key to sort on, or `$created_at` / `$updated_at`. Nulls sort last. Omit for newest first.",
                        "example": "balance"
                    },
                    {
                        "name": "dir",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ],
                            "default": "desc"
                        },
                        "description": "Sort direction. Anything else answers 422.",
                        "example": "desc"
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "The `next_cursor` of the previous page. Send the same `filter`, `q`, `sort` and `dir` with it. Opaque: a cursor that does not decode starts again from the first page rather than failing.",
                        "example": "eyJjIjoiMjAyNi0wOS0wOFQwNzo0MToxMi40MTgyMDZaIiwiaSI6IjJjN2UxYTliLTNkNGYtNGE1Yi04YzZkLTdlOGY5YTBiMWMyZCJ9"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 200,
                            "default": 50
                        },
                        "description": "Records per page, 1\u2013200. Values above 200 are clamped, not refused.",
                        "example": 50
                    },
                    {
                        "name": "with_count",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "boolean",
                            "default": false
                        },
                        "description": "Also count every record matching `filter` and `q`, into `count`. Costs a second query \u2014 ask on the first page only.",
                        "example": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of records.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataRecordPage"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "records": [
                                                {
                                                    "id": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                                    "data": {
                                                        "name": "Asha Mwinyi",
                                                        "phone": "+255712345678",
                                                        "region": "dar",
                                                        "opt_in": true,
                                                        "balance": 15000
                                                    },
                                                    "source": "api",
                                                    "created_at": "2026-09-08T07:41:12.418206Z",
                                                    "updated_at": "2026-09-08T07:41:12.418206Z",
                                                    "title": "Asha Mwinyi"
                                                },
                                                {
                                                    "id": "7f3a2b1c-9d8e-4f7a-b6c5-d4e3f2a1b0c9",
                                                    "data": {
                                                        "name": "Juma Hassan",
                                                        "phone": "+255754000111",
                                                        "region": "arusha",
                                                        "opt_in": true,
                                                        "balance": 2500
                                                    },
                                                    "source": "ui",
                                                    "created_at": "2026-09-06T11:03:44.902113Z",
                                                    "updated_at": "2026-09-07T08:20:01.117650Z",
                                                    "title": "Juma Hassan"
                                                }
                                            ],
                                            "next_cursor": "eyJjIjoiMjAyNi0wOS0wNlQxMTowMzo0NC45MDIxMTNaIiwiaSI6IjdmM2EyYjFjLTlkOGUtNGY3YS1iNmM1LWQ0ZTNmMmExYjBjOSJ9",
                                            "has_more": true,
                                            "count": 1286,
                                            "served_at": "2026-09-08T07:45:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No table with that id for this tenant (or the id is not a UUID).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Malformed query or invalid record value. Missing request data may use the standard v3 envelope; expected data refusals use DataError.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        },
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "validation_error",
                                                "message": "The supplied data or query is invalid.",
                                                "retryable": false
                                            },
                                            "message": "The supplied data or query is invalid.",
                                            "code": "validation_error"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "501": {
                        "description": "The field type does not support the operator, or this sort needs an index.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "not_supported",
                                                "message": "Refused (sort_needs_index): Index the column 'region' to sort on it.",
                                                "retryable": false,
                                                "field": "region",
                                                "details": {
                                                    "reason": "sort_needs_index"
                                                }
                                            },
                                            "message": "Refused (sort_needs_index): Index the column 'region' to sort on it.",
                                            "code": "not_supported"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "post": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataRecordsCreate",
                "x-permission": "data.records.edit",
                "x-permission-scope": "controller",
                "summary": "Create a record",
                "description": "Adds one record. Every key in `data` is validated and coerced through its column's type (a phone becomes E.164, a number becomes a number), required columns must be present, unique columns must not collide, and the whole record must fit in 8 KB. The record is stamped `source: \"api\"`.\n\nKeys that are not columns of the table are refused, so read the schema first.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "data"
                                ],
                                "properties": {
                                    "data": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "The values, keyed by column key. Every required column must be present; other columns may be omitted."
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "data": {
                                            "name": "Asha Mwinyi",
                                            "phone": "0712345678",
                                            "region": "dar",
                                            "opt_in": true,
                                            "balance": 15000
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created. The record as stored, values coerced.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "record"
                                    ],
                                    "properties": {
                                        "record": {
                                            "$ref": "#/components/schemas/DataRecord",
                                            "description": "The record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "record": {
                                                "id": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                                "data": {
                                                    "name": "Asha Mwinyi",
                                                    "phone": "+255712345678",
                                                    "region": "dar",
                                                    "opt_in": true,
                                                    "balance": 15000
                                                },
                                                "source": "api",
                                                "created_at": "2026-09-08T07:41:12.418206Z",
                                                "updated_at": "2026-09-08T07:41:12.418206Z",
                                                "title": "Asha Mwinyi"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key issuer or table grant forbids the write, or a state transition requires a permission the caller lacks.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        },
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        }
                                    ]
                                },
                                "example": {
                                    "status": "error",
                                    "message": "You do not have permission to perform this action."
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No table with that id for this tenant (or the id is not a UUID).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Malformed query or invalid record value. Missing request data may use the standard v3 envelope; expected data refusals use DataError.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        },
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "validation_error",
                                                "message": "The supplied data or query is invalid.",
                                                "retryable": false
                                            },
                                            "message": "The supplied data or query is invalid.",
                                            "code": "validation_error"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "402": {
                        "description": "Table/account quota prevents storage; error.details names the quota and allowance.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "quota_exceeded",
                                                "message": "The table has reached its record allowance.",
                                                "retryable": false,
                                                "details": {
                                                    "quota": "quota_records",
                                                    "limit": 500000,
                                                    "used": 500000
                                                }
                                            },
                                            "message": "The table has reached its record allowance.",
                                            "code": "quota_exceeded"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A unique-value or status-transition conflict prevented the write.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "conflict",
                                                "message": "The record was refused. A unique value or state transition conflicts with current data.",
                                                "retryable": false
                                            },
                                            "message": "The record was refused. A unique value or state transition conflicts with current data.",
                                            "code": "conflict"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/data/tables/{table}/records/{record}": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataRecordsGet",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "Read a record",
                "description": "One record by id. A deleted record is a 404.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    },
                    {
                        "$ref": "#/components/parameters/DataRecordId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "record"
                                    ],
                                    "properties": {
                                        "record": {
                                            "$ref": "#/components/schemas/DataRecord",
                                            "description": "The record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "record": {
                                                "id": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                                "data": {
                                                    "name": "Asha Mwinyi",
                                                    "phone": "+255712345678",
                                                    "region": "dar",
                                                    "opt_in": true,
                                                    "balance": 15000
                                                },
                                                "source": "api",
                                                "created_at": "2026-09-08T07:41:12.418206Z",
                                                "updated_at": "2026-09-08T07:41:12.418206Z",
                                                "title": "Asha Mwinyi"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Unknown/hidden table uses the standard v3 envelope; unknown or deleted record uses the data error envelope.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        },
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "No such record in this table.",
                                                "retryable": false,
                                                "field": "$id"
                                            },
                                            "message": "No such record in this table.",
                                            "code": "not_found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataRecordsUpdate",
                "x-permission": "data.records.edit",
                "x-permission-scope": "controller",
                "summary": "Update a record",
                "description": "Changes only the keys you send; everything else keeps its value. A key set to `null` is cleared \u2014 unless the column is required, which answers 422. Values go through the same validation and coercion as a create. `source` is fixed at create and does not change here.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    },
                    {
                        "$ref": "#/components/parameters/DataRecordId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "data"
                                ],
                                "properties": {
                                    "data": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "Only the keys to change. `null` clears a key."
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "data": {
                                            "region": "arusha",
                                            "balance": 12500
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Updated. The whole record as it now stands.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "record"
                                    ],
                                    "properties": {
                                        "record": {
                                            "$ref": "#/components/schemas/DataRecord",
                                            "description": "The record."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "record": {
                                                "id": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                                "data": {
                                                    "name": "Asha Mwinyi",
                                                    "phone": "+255712345678",
                                                    "region": "arusha",
                                                    "opt_in": true,
                                                    "balance": 12500
                                                },
                                                "source": "api",
                                                "created_at": "2026-09-08T07:41:12.418206Z",
                                                "updated_at": "2026-09-08T09:12:40.006511Z",
                                                "title": "Asha Mwinyi"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key issuer or table grant forbids the write, or a state transition requires a permission the caller lacks.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        },
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        }
                                    ]
                                },
                                "example": {
                                    "status": "error",
                                    "message": "You do not have permission to perform this action."
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Unknown/hidden table uses the standard v3 envelope; unknown or deleted record uses the data error envelope.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        },
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "No such record in this table.",
                                                "retryable": false,
                                                "field": "$id"
                                            },
                                            "message": "No such record in this table.",
                                            "code": "not_found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Malformed query or invalid record value. Missing request data may use the standard v3 envelope; expected data refusals use DataError.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        },
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "validation_error",
                                                "message": "The supplied data or query is invalid.",
                                                "retryable": false
                                            },
                                            "message": "The supplied data or query is invalid.",
                                            "code": "validation_error"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "402": {
                        "description": "Table/account quota prevents storage; error.details names the quota and allowance.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "quota_exceeded",
                                                "message": "The table has reached its record allowance.",
                                                "retryable": false,
                                                "details": {
                                                    "quota": "quota_records",
                                                    "limit": 500000,
                                                    "used": 500000
                                                }
                                            },
                                            "message": "The table has reached its record allowance.",
                                            "code": "quota_exceeded"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "A unique-value or status-transition conflict prevented the write.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "conflict",
                                                "message": "The record was refused. A unique value or state transition conflicts with current data.",
                                                "retryable": false
                                            },
                                            "message": "The record was refused. A unique value or state transition conflicts with current data.",
                                            "code": "conflict"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataRecordsDelete",
                "x-permission": "data.records.edit",
                "x-permission-scope": "controller",
                "summary": "Delete a record",
                "description": "Soft-deletes one record: it leaves every list and read from now on and stops counting against the records quota. Deleting it twice is a 404.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    },
                    {
                        "$ref": "#/components/parameters/DataRecordId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "deleted"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "enum": [
                                                true
                                            ],
                                            "description": "Always true on success."
                                        },
                                        "deleted": {
                                            "type": "integer",
                                            "enum": [
                                                1
                                            ],
                                            "description": "How many records were deleted \u2014 always 1 here."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "ok": true,
                                            "deleted": 1
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.records.edit, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.records.edit\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Unknown/hidden table uses the standard v3 envelope; unknown or deleted record uses the data error envelope.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        },
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "not_found",
                                                "message": "No such record in this table.",
                                                "retryable": false,
                                                "field": "$id"
                                            },
                                            "message": "No such record in this table.",
                                            "code": "not_found"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/tables/{table}/records/{record}/history": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataRecordHistory",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "Read a record's history",
                "description": "Every change made to one record, newest first: what was created, updated or deleted, which fields moved and from what to what, who did it and through which surface (the web app, an API key, an MCP connection, a message flow, an IVR call or a schedule), and the reason when one was given. Pages 50 at a time; pass the timestamp returned as next_before back as the before query parameter to read the page after it. A record nobody has changed answers with an empty list, not a 404.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    },
                    {
                        "$ref": "#/components/parameters/DataRecordId"
                    },
                    {
                        "name": "before",
                        "in": "query",
                        "required": false,
                        "description": "Read the page older than this timestamp \u2014 the next_before value from the previous page.",
                        "schema": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2026-09-08 14:31:07.812345+03:00"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The record's history.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "history",
                                        "has_more"
                                    ],
                                    "properties": {
                                        "history": {
                                            "type": "array",
                                            "description": "The changes, newest first.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The history entry's id."
                                                    },
                                                    "action": {
                                                        "type": "string",
                                                        "enum": [
                                                            "create",
                                                            "update",
                                                            "delete",
                                                            "restore",
                                                            "bulk_delete"
                                                        ],
                                                        "description": "What happened to the record."
                                                    },
                                                    "changes": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "Per field, the value before and after. A create lists every field from null; a delete lists every field to null."
                                                    },
                                                    "actor": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "Who made the change: kind (user, api, mcp, flow, ivr, schedule, system), id and a label."
                                                    },
                                                    "source": {
                                                        "type": "string",
                                                        "description": "The surface the write came through."
                                                    },
                                                    "reason": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "Why, when the caller gave a reason."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the change was made."
                                                    },
                                                    "record_id": {
                                                        "type": "string",
                                                        "description": "Record UUID described by this audit entry.",
                                                        "format": "uuid"
                                                    },
                                                    "changed": {
                                                        "type": "array",
                                                        "description": "Keys changed in this entry.",
                                                        "items": {
                                                            "type": "string"
                                                        }
                                                    }
                                                }
                                            }
                                        },
                                        "has_more": {
                                            "type": "boolean",
                                            "description": "Whether an older page exists."
                                        },
                                        "next_before": {
                                            "type": "string",
                                            "format": "date-time",
                                            "nullable": true,
                                            "description": "Pass back as before to read the next page."
                                        },
                                        "columns": {
                                            "type": "object",
                                            "additionalProperties": true,
                                            "description": "Field key to its label, so a change can be shown with the field's name."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "history": [
                                                {
                                                    "id": "0192f3c4-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
                                                    "action": "update",
                                                    "changes": {
                                                        "status": {
                                                            "from": "pending",
                                                            "to": "paid"
                                                        }
                                                    },
                                                    "actor": {
                                                        "kind": "mcp",
                                                        "id": 41,
                                                        "label": "Claude"
                                                    },
                                                    "source": "mcp",
                                                    "reason": null,
                                                    "created_at": "2026-09-08T14:31:07.812345+03:00"
                                                }
                                            ],
                                            "has_more": false,
                                            "next_before": null,
                                            "columns": {
                                                "status": "Status"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Invalid UUID or unknown/hidden table. A valid record UUID with no history returns an empty history list, including after deletion.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/groups": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataGroupsList",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "List table groups",
                "description": "Every group this tenant has defined, in display order. A group is a named folder of related tables (customers, orders, payments) with a report layer across them; a table belongs to at most one group.",
                "responses": {
                    "200": {
                        "description": "The groups.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "groups"
                                    ],
                                    "properties": {
                                        "groups": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/DataTableGroup"
                                            },
                                            "description": "The groups, in display order (position, then name)."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "groups": [
                                                {
                                                    "id": "7c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                                                    "name": "Mauzo",
                                                    "slug": "mauzo",
                                                    "description": "Wateja na oda zao.",
                                                    "icon": "\ud83d\uded2",
                                                    "color": "amber",
                                                    "position": 0,
                                                    "tables_count": 2,
                                                    "records_count": 61234,
                                                    "created_at": "2026-09-08T09:00:00+00:00",
                                                    "updated_at": "2026-09-08T09:00:00+00:00"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/groups/{group}": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataGroupGet",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "Read a group",
                "description": "The group, its member tables (each with its columns, headline total and records created in the last 30 days) and its saved cross-table reports.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataGroupId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The group.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "group",
                                        "tables",
                                        "reports"
                                    ],
                                    "properties": {
                                        "group": {
                                            "$ref": "#/components/schemas/DataTableGroup",
                                            "description": "The group."
                                        },
                                        "tables": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/DataGroupTableCard"
                                            },
                                            "description": "Member tables in the group's order, each with its columns and its last-30-days card."
                                        },
                                        "reports": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/DataGroupReport"
                                            },
                                            "description": "Saved cross-table reports, pinned first."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "group": {
                                                "id": "7c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                                                "name": "Mauzo",
                                                "slug": "mauzo",
                                                "description": "Wateja na oda zao.",
                                                "icon": "\ud83d\uded2",
                                                "color": "amber",
                                                "position": 0,
                                                "tables_count": 2,
                                                "records_count": 61234,
                                                "created_at": "2026-09-08T09:00:00+00:00",
                                                "updated_at": "2026-09-08T09:00:00+00:00"
                                            },
                                            "tables": [
                                                {
                                                    "id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                    "name": "Oda",
                                                    "slug": "orders",
                                                    "icon": "\ud83e\uddfe",
                                                    "records_count": 52014,
                                                    "columns_count": 4,
                                                    "headline": {
                                                        "label": "Total Kiasi (TZS)",
                                                        "fn": "sum",
                                                        "column": "amount",
                                                        "value": 5466022000,
                                                        "unit": "TZS"
                                                    },
                                                    "created_last_range": 812,
                                                    "drill": {
                                                        "table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                        "filter": {
                                                            "all": [
                                                                {
                                                                    "column": "$created_at",
                                                                    "op": "between",
                                                                    "value": [
                                                                        "2026-08-10T00:00:00Z",
                                                                        "2026-09-09T00:00:00Z"
                                                                    ]
                                                                }
                                                            ]
                                                        },
                                                        "range": {
                                                            "from": "2026-08-10T00:00:00Z",
                                                            "to": "2026-09-09T00:00:00Z"
                                                        }
                                                    },
                                                    "columns": []
                                                }
                                            ],
                                            "reports": [
                                                {
                                                    "id": "b2c3d4e5-f6a7-4b8c-9d0e-1f2a3b4c5d6e",
                                                    "group_id": "7c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
                                                    "name": "Mauzo kwa wiki",
                                                    "description": null,
                                                    "definition": {
                                                        "series": [
                                                            {
                                                                "table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                                "metric": {
                                                                    "fn": "sum",
                                                                    "column": "amount"
                                                                },
                                                                "filters": null,
                                                                "label": "Oda"
                                                            },
                                                            {
                                                                "table_id": "4e8d9c0b-1a2f-4b3c-8d4e-5f6a7b8c9d0e",
                                                                "metric": {
                                                                    "fn": "count"
                                                                },
                                                                "filters": null,
                                                                "label": "Wateja"
                                                            }
                                                        ],
                                                        "dimension": {
                                                            "column": "$created_at",
                                                            "bucket": "week"
                                                        },
                                                        "date_range": {
                                                            "relative": "last_90_days"
                                                        },
                                                        "chart": "line"
                                                    },
                                                    "is_pinned": true,
                                                    "is_default": false,
                                                    "created_at": "2026-09-08T09:00:00+00:00",
                                                    "updated_at": "2026-09-08T09:00:00+00:00"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No group with that id for this tenant (or the id is not a UUID).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/groups/{group}/overview": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataGroupOverview",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "summary": "Read a group's overview",
                "description": "Totals, one card per member table, records over time stacked by table, every amount-like column totalled, and the relations between member tables \u2014 for a range. Every card carries a `drill` you can pass to the records endpoint as `filter`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataGroupId"
                    },
                    {
                        "name": "range",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "default": "last_30_days"
                        },
                        "description": "A relative preset (today, yesterday, last_7_days, last_30_days, last_90_days, this_month, last_month) or a JSON period `{\"from\":\"YYYY-MM-DD\",\"to\":\"YYYY-MM-DD\"}`. `from`/`to` query parameters are accepted too.",
                        "example": "last_30_days"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The overview.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataGroupOverview"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "totals": {
                                                "tables": 2,
                                                "records": 61234,
                                                "storage_bytes": 12345678
                                            },
                                            "tables": [
                                                {
                                                    "id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                    "name": "Oda",
                                                    "slug": "orders",
                                                    "icon": "\ud83e\uddfe",
                                                    "records_count": 52014,
                                                    "columns_count": 4,
                                                    "headline": {
                                                        "label": "Total Kiasi (TZS)",
                                                        "fn": "sum",
                                                        "column": "amount",
                                                        "value": 5466022000,
                                                        "unit": "TZS"
                                                    },
                                                    "created_last_range": 812,
                                                    "drill": {
                                                        "table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                        "filter": {
                                                            "all": [
                                                                {
                                                                    "column": "$created_at",
                                                                    "op": "between",
                                                                    "value": [
                                                                        "2026-08-10T00:00:00Z",
                                                                        "2026-09-09T00:00:00Z"
                                                                    ]
                                                                }
                                                            ]
                                                        },
                                                        "range": {
                                                            "from": "2026-08-10T00:00:00Z",
                                                            "to": "2026-09-09T00:00:00Z"
                                                        }
                                                    }
                                                }
                                            ],
                                            "over_time": {
                                                "bucket": "day",
                                                "rows": [
                                                    {
                                                        "bucket": "2026-09-01",
                                                        "total": 42,
                                                        "by_table": {
                                                            "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b": 30,
                                                            "4e8d9c0b-1a2f-4b3c-8d4e-5f6a7b8c9d0e": 12
                                                        },
                                                        "drill": {
                                                            "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b": {
                                                                "table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                                "filter": {
                                                                    "all": [
                                                                        {
                                                                            "column": "$created_at",
                                                                            "op": "between",
                                                                            "value": [
                                                                                "2026-09-01T00:00:00Z",
                                                                                "2026-09-02T00:00:00Z"
                                                                            ]
                                                                        }
                                                                    ]
                                                                },
                                                                "range": {
                                                                    "from": "2026-09-01T00:00:00Z",
                                                                    "to": "2026-09-02T00:00:00Z"
                                                                }
                                                            }
                                                        }
                                                    }
                                                ]
                                            },
                                            "headlines": [
                                                {
                                                    "table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                    "table": "Oda",
                                                    "label": "Total Kiasi (TZS)",
                                                    "fn": "sum",
                                                    "column": "amount",
                                                    "value": 5466022000,
                                                    "unit": "TZS",
                                                    "chart": "number",
                                                    "drill": {
                                                        "table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                        "filter": {
                                                            "all": [
                                                                {
                                                                    "column": "$created_at",
                                                                    "op": "between",
                                                                    "value": [
                                                                        "2026-08-10T00:00:00Z",
                                                                        "2026-09-09T00:00:00Z"
                                                                    ]
                                                                }
                                                            ]
                                                        },
                                                        "range": {
                                                            "from": "2026-08-10T00:00:00Z",
                                                            "to": "2026-09-09T00:00:00Z"
                                                        }
                                                    }
                                                }
                                            ],
                                            "relations": [
                                                {
                                                    "from_table_id": "9d2f4c1e-7b8a-4e0f-9a3b-5c6d7e8f9a0b",
                                                    "from_column": "customer",
                                                    "to_table_id": "4e8d9c0b-1a2f-4b3c-8d4e-5f6a7b8c9d0e"
                                                }
                                            ],
                                            "range": {
                                                "from": "2026-08-10T00:00:00Z",
                                                "to": "2026-09-09T00:00:00Z",
                                                "relative": "last_30_days"
                                            },
                                            "computed_at": "2026-09-08T10:11:12Z"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold data.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"data.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No group with that id for this tenant (or the id is not a UUID).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Malformed query or invalid record value. Missing request data may use the standard v3 envelope; expected data refusals use DataError.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/DataError"
                                        },
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        }
                                    ]
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "error": {
                                                "code": "validation_error",
                                                "message": "The supplied data or query is invalid.",
                                                "retryable": false
                                            },
                                            "message": "The supplied data or query is invalid.",
                                            "code": "validation_error"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/payments": {
            "get": {
                "tags": [
                    "Payments"
                ],
                "operationId": "v3PaymentsIndex",
                "x-permission": "payments.view",
                "x-permission-scope": "controller",
                "summary": "List payments",
                "description": "Read tenant payment intents newest first. Requires payments.view on the key issuer. The native response is {data:[...],meta:{current_page,per_page,total,last_page}}; pagination defaults to 25 and caps at 100. state=open selects draft, pending and authorised; unknown state input currently leaves results unfiltered. amount_minor and refunded_minor are integers on a fixed 100-minor-units-per-major-unit scale, including TZS. Use formatted amount for display. paid, partly_refunded and refunded mean funds settled at some point; inspect refunded_minor to determine what has been returned. This REST surface provides reads only.",
                "parameters": [
                    {
                        "name": "state",
                        "in": "query",
                        "required": false,
                        "description": "Filter by state. open means draft, pending or authorised; omitted/all means no filter. Unknown input also currently leaves the list unfiltered.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "open",
                                "draft",
                                "pending",
                                "authorised",
                                "paid",
                                "failed",
                                "expired",
                                "cancelled",
                                "refunded",
                                "partly_refunded"
                            ],
                            "example": "open"
                        }
                    },
                    {
                        "name": "subject_id",
                        "in": "query",
                        "required": false,
                        "description": "Only payments raised for this record \u2014 an order id, a Daftari record id, an invoice number.",
                        "schema": {
                            "type": "string",
                            "example": "1214"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/PerPage",
                        "description": "Page size, default 25 and maximum 100. limit is also accepted and takes precedence over per_page."
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The page of payments.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "description": "The payments on this page, newest first.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The payment's id. Time-ordered, so sorting by it sorts by when it was raised."
                                                    },
                                                    "reference": {
                                                        "type": "string",
                                                        "description": "The human reference, unique in this workspace: PAY-YYYYMMDD-NNNN. This is what a person quotes down a phone line."
                                                    },
                                                    "state": {
                                                        "type": "string",
                                                        "enum": [
                                                            "draft",
                                                            "pending",
                                                            "authorised",
                                                            "paid",
                                                            "failed",
                                                            "expired",
                                                            "cancelled",
                                                            "refunded",
                                                            "partly_refunded"
                                                        ],
                                                        "description": "Where the ask got to. Only paid, partly_refunded and refunded mean money actually arrived."
                                                    },
                                                    "state_label": {
                                                        "type": "string",
                                                        "description": "The state written for a person to read."
                                                    },
                                                    "is_open": {
                                                        "type": "boolean",
                                                        "description": "Whether the payment is still waiting on the customer."
                                                    },
                                                    "is_settled": {
                                                        "type": "boolean",
                                                        "description": "Whether money arrived, whatever has since been given back."
                                                    },
                                                    "amount_minor": {
                                                        "type": "integer",
                                                        "description": "Integer minor units at a fixed scale of 100 per major unit, including TZS: 40000 represents TZS 400. Use amount for formatted display."
                                                    },
                                                    "amount": {
                                                        "type": "string",
                                                        "description": "The same amount formatted with its currency code, for showing to a person."
                                                    },
                                                    "currency": {
                                                        "type": "string",
                                                        "description": "ISO 4217 code."
                                                    },
                                                    "refunded_minor": {
                                                        "type": "integer",
                                                        "description": "How much of the amount has already been given back, in minor units."
                                                    },
                                                    "refunded": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "The refunded total formatted, or null when nothing has been refunded."
                                                    },
                                                    "refundable_minor": {
                                                        "type": "integer",
                                                        "description": "How much could still be refunded, in minor units."
                                                    },
                                                    "payer": {
                                                        "type": "object",
                                                        "nullable": true,
                                                        "additionalProperties": true,
                                                        "description": "Who is paying: name, phone and email, only as far as they were given."
                                                    },
                                                    "method": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "How the customer was asked: ussd_push, link or lipa."
                                                    },
                                                    "provider": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "The gateway the request went to."
                                                    },
                                                    "subject_type": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "What is being paid for \u2014 an order, a data table, an invoice."
                                                    },
                                                    "subject_id": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "The id of the thing being paid for."
                                                    },
                                                    "is_refund": {
                                                        "type": "boolean",
                                                        "description": "Whether this payment is itself a refund of another one."
                                                    },
                                                    "refund_of": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "nullable": true,
                                                        "description": "The payment this one gives money back for."
                                                    },
                                                    "refund_reason": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "Why the refund was raised."
                                                    },
                                                    "attempts": {
                                                        "type": "integer",
                                                        "description": "How many times the provider has been asked."
                                                    },
                                                    "last_error": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "What went wrong last time, in plain words. Never carries a credential."
                                                    },
                                                    "expires_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When the ask stops being answerable."
                                                    },
                                                    "settled_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When the money arrived."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When the payment was raised."
                                                    },
                                                    "next_states": {
                                                        "type": "array",
                                                        "items": {
                                                            "type": "string"
                                                        },
                                                        "description": "The states this payment may legally move to next."
                                                    },
                                                    "checkout_url": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "The page to send the customer to, when the method produced one."
                                                    },
                                                    "payment_token": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "The short lipa number the customer pays from any wallet app."
                                                    },
                                                    "token_expires_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When that lipa number stops working."
                                                    }
                                                }
                                            }
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "Where this page sits in the whole set.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "The page returned."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "How many rows a page holds."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "How many payments match in total."
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "The highest page number available."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": [
                                                {
                                                    "id": "0192f3c4-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
                                                    "reference": "PAY-20260908-0042",
                                                    "state": "paid",
                                                    "state_label": "Paid",
                                                    "is_open": false,
                                                    "is_settled": true,
                                                    "amount_minor": 4000000,
                                                    "amount": "TZS 40,000",
                                                    "currency": "TZS",
                                                    "refunded_minor": 0,
                                                    "refunded": null,
                                                    "refundable_minor": 4000000,
                                                    "payer": {
                                                        "name": "Asha Mushi",
                                                        "phone": "255712345678"
                                                    },
                                                    "method": "ussd_push",
                                                    "provider": "selcom",
                                                    "subject_type": "App\\Models\\WaOrder",
                                                    "subject_id": "1214",
                                                    "is_refund": false,
                                                    "refund_of": null,
                                                    "refund_reason": null,
                                                    "attempts": 1,
                                                    "last_error": null,
                                                    "expires_at": "2026-09-08T17:31:07+03:00",
                                                    "settled_at": "2026-09-08T14:34:52+03:00",
                                                    "created_at": "2026-09-08T14:31:07+03:00",
                                                    "next_states": [
                                                        "partly_refunded",
                                                        "refunded"
                                                    ],
                                                    "checkout_url": null,
                                                    "payment_token": null,
                                                    "token_expires_at": null
                                                }
                                            ],
                                            "meta": {
                                                "current_page": 1,
                                                "per_page": 25,
                                                "total": 1,
                                                "last_page": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold payments.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"payments.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such workspace for this token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/payments/{payment}": {
            "get": {
                "tags": [
                    "Payments"
                ],
                "operationId": "v3PaymentShow",
                "x-permission": "payments.view",
                "x-permission-scope": "controller",
                "summary": "Read one payment",
                "description": "One payment in full: the amount, who was asked, where it got to, everything that has happened to it in order, what it wrote in the books, and any refunds raised against it. The timeline is the answer to \"the customer says they paid and the record says otherwise\", and it is append-only \u2014 nothing in it is ever edited. Accepts the payment id or its human reference.",
                "parameters": [
                    {
                        "name": "payment",
                        "in": "path",
                        "required": true,
                        "description": "The payment id, or its human reference (PAY-YYYYMMDD-NNNN). A payment belonging to another tenant answers 404.",
                        "schema": {
                            "type": "string",
                            "example": "PAY-20260908-0042"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The payment, its timeline, its ledger entries and its refunds.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The payment with its whole story.",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "format": "uuid",
                                                    "description": "The payment's id. Time-ordered, so sorting by it sorts by when it was raised."
                                                },
                                                "reference": {
                                                    "type": "string",
                                                    "description": "The human reference, unique in this workspace: PAY-YYYYMMDD-NNNN. This is what a person quotes down a phone line."
                                                },
                                                "state": {
                                                    "type": "string",
                                                    "enum": [
                                                        "draft",
                                                        "pending",
                                                        "authorised",
                                                        "paid",
                                                        "failed",
                                                        "expired",
                                                        "cancelled",
                                                        "refunded",
                                                        "partly_refunded"
                                                    ],
                                                    "description": "Where the ask got to. Only paid, partly_refunded and refunded mean money actually arrived."
                                                },
                                                "state_label": {
                                                    "type": "string",
                                                    "description": "The state written for a person to read."
                                                },
                                                "is_open": {
                                                    "type": "boolean",
                                                    "description": "Whether the payment is still waiting on the customer."
                                                },
                                                "is_settled": {
                                                    "type": "boolean",
                                                    "description": "Whether money arrived, whatever has since been given back."
                                                },
                                                "amount_minor": {
                                                    "type": "integer",
                                                    "description": "Integer minor units at a fixed scale of 100 per major unit, including TZS: 40000 represents TZS 400. Use amount for formatted display."
                                                },
                                                "amount": {
                                                    "type": "string",
                                                    "description": "The same amount formatted with its currency code, for showing to a person."
                                                },
                                                "currency": {
                                                    "type": "string",
                                                    "description": "ISO 4217 code."
                                                },
                                                "refunded_minor": {
                                                    "type": "integer",
                                                    "description": "How much of the amount has already been given back, in minor units."
                                                },
                                                "refunded": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "The refunded total formatted, or null when nothing has been refunded."
                                                },
                                                "refundable_minor": {
                                                    "type": "integer",
                                                    "description": "How much could still be refunded, in minor units."
                                                },
                                                "payer": {
                                                    "type": "object",
                                                    "nullable": true,
                                                    "additionalProperties": true,
                                                    "description": "Who is paying: name, phone and email, only as far as they were given."
                                                },
                                                "method": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "How the customer was asked: ussd_push, link or lipa."
                                                },
                                                "provider": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "The gateway the request went to."
                                                },
                                                "subject_type": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "What is being paid for \u2014 an order, a data table, an invoice."
                                                },
                                                "subject_id": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "The id of the thing being paid for."
                                                },
                                                "is_refund": {
                                                    "type": "boolean",
                                                    "description": "Whether this payment is itself a refund of another one."
                                                },
                                                "refund_of": {
                                                    "type": "string",
                                                    "format": "uuid",
                                                    "nullable": true,
                                                    "description": "The payment this one gives money back for."
                                                },
                                                "refund_reason": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "Why the refund was raised."
                                                },
                                                "attempts": {
                                                    "type": "integer",
                                                    "description": "How many times the provider has been asked."
                                                },
                                                "last_error": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "What went wrong last time, in plain words. Never carries a credential."
                                                },
                                                "expires_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "nullable": true,
                                                    "description": "When the ask stops being answerable."
                                                },
                                                "settled_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "nullable": true,
                                                    "description": "When the money arrived."
                                                },
                                                "created_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When the payment was raised."
                                                },
                                                "next_states": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "The states this payment may legally move to next."
                                                },
                                                "checkout_url": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "The page to send the customer to, when the method produced one."
                                                },
                                                "payment_token": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "The short lipa number the customer pays from any wallet app."
                                                },
                                                "token_expires_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "nullable": true,
                                                    "description": "When that lipa number stops working."
                                                },
                                                "created_by": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "The person who raised the payment, when a person did."
                                                },
                                                "timeline": {
                                                    "type": "array",
                                                    "description": "Everything that has happened to this payment, oldest first. Append-only: nothing here is ever edited.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "id": {
                                                                "type": "string",
                                                                "format": "uuid",
                                                                "description": "The event's id."
                                                            },
                                                            "type": {
                                                                "type": "string",
                                                                "description": "created, collect_requested, state_changed, refund_requested, reconciled or drift."
                                                            },
                                                            "from_state": {
                                                                "type": "string",
                                                                "nullable": true,
                                                                "description": "The state before this event."
                                                            },
                                                            "to_state": {
                                                                "type": "string",
                                                                "nullable": true,
                                                                "description": "The state after it."
                                                            },
                                                            "source": {
                                                                "type": "string",
                                                                "description": "Which door caused it: api, webhook, reconciler, flow, mcp, client or system."
                                                            },
                                                            "message": {
                                                                "type": "string",
                                                                "nullable": true,
                                                                "description": "What happened, in plain words."
                                                            },
                                                            "occurred_at": {
                                                                "type": "string",
                                                                "format": "date-time",
                                                                "description": "When."
                                                            }
                                                        }
                                                    }
                                                },
                                                "ledger": {
                                                    "type": "array",
                                                    "description": "What this payment wrote in the books. Append-only and always balanced: every posting moves the same amount out of one account as into another.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "entry_no": {
                                                                "type": "integer",
                                                                "description": "The ledger's own sequence number."
                                                            },
                                                            "kind": {
                                                                "type": "string",
                                                                "description": "payment, refund, payout, fee, adjustment, charge, hold or release."
                                                            },
                                                            "direction": {
                                                                "type": "string",
                                                                "enum": [
                                                                    "debit",
                                                                    "credit"
                                                                ],
                                                                "description": "Which way the money went. The amount is always positive; this carries the sign."
                                                            },
                                                            "account": {
                                                                "type": "string",
                                                                "enum": [
                                                                    "customer",
                                                                    "business",
                                                                    "platform",
                                                                    "provider"
                                                                ],
                                                                "description": "Whose position moved."
                                                            },
                                                            "amount_minor": {
                                                                "type": "integer",
                                                                "description": "Integer amount on the payment layer fixed scale of 100 minor units per major currency unit."
                                                            },
                                                            "amount": {
                                                                "type": "string",
                                                                "description": "The same amount formatted."
                                                            },
                                                            "occurred_at": {
                                                                "type": "string",
                                                                "format": "date-time",
                                                                "description": "When the money moved."
                                                            }
                                                        }
                                                    }
                                                },
                                                "refunds": {
                                                    "type": "array",
                                                    "description": "Refunds raised against this payment. Each is a payment in its own right, linked back by refund_of.",
                                                    "items": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "A refund, in the same shape as any other payment."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "id": "0192f3c4-5a6b-7c8d-9e0f-1a2b3c4d5e6f",
                                                "reference": "PAY-20260908-0042",
                                                "state": "paid",
                                                "state_label": "Paid",
                                                "is_open": false,
                                                "is_settled": true,
                                                "amount_minor": 4000000,
                                                "amount": "TZS 40,000",
                                                "currency": "TZS",
                                                "refunded_minor": 0,
                                                "refunded": null,
                                                "refundable_minor": 4000000,
                                                "payer": {
                                                    "name": "Asha Mushi",
                                                    "phone": "255712345678"
                                                },
                                                "method": "ussd_push",
                                                "provider": "selcom",
                                                "subject_type": "App\\Models\\WaOrder",
                                                "subject_id": "1214",
                                                "is_refund": false,
                                                "refund_of": null,
                                                "refund_reason": null,
                                                "attempts": 1,
                                                "last_error": null,
                                                "expires_at": "2026-09-08T17:31:07+03:00",
                                                "settled_at": "2026-09-08T14:34:52+03:00",
                                                "created_at": "2026-09-08T14:31:07+03:00",
                                                "next_states": [
                                                    "partly_refunded",
                                                    "refunded"
                                                ],
                                                "checkout_url": null,
                                                "payment_token": null,
                                                "token_expires_at": null,
                                                "created_by": "Neema Kimaro",
                                                "timeline": [
                                                    {
                                                        "id": "0192f3c4-5a6b-7c8d-9e0f-1a2b3c4d5e70",
                                                        "type": "created",
                                                        "from_state": null,
                                                        "to_state": "draft",
                                                        "source": "api",
                                                        "message": "TZS 40,000 asked for, for App\\Models\\WaOrder 1214.",
                                                        "occurred_at": "2026-09-08T14:31:07+03:00"
                                                    },
                                                    {
                                                        "id": "0192f3c4-5a6b-7c8d-9e0f-1a2b3c4d5e71",
                                                        "type": "collect_requested",
                                                        "from_state": "draft",
                                                        "to_state": "pending",
                                                        "source": "api",
                                                        "message": "Asked the provider for the money.",
                                                        "occurred_at": "2026-09-08T14:31:08+03:00"
                                                    },
                                                    {
                                                        "id": "0192f3c4-5a6b-7c8d-9e0f-1a2b3c4d5e72",
                                                        "type": "state_changed",
                                                        "from_state": "pending",
                                                        "to_state": "paid",
                                                        "source": "webhook",
                                                        "message": "",
                                                        "occurred_at": "2026-09-08T14:34:52+03:00"
                                                    }
                                                ],
                                                "ledger": [
                                                    {
                                                        "entry_no": 8121,
                                                        "kind": "payment",
                                                        "direction": "debit",
                                                        "account": "customer",
                                                        "amount_minor": 4000000,
                                                        "amount": "TZS 40,000",
                                                        "occurred_at": "2026-09-08T14:34:52+03:00"
                                                    },
                                                    {
                                                        "entry_no": 8122,
                                                        "kind": "payment",
                                                        "direction": "credit",
                                                        "account": "business",
                                                        "amount_minor": 4000000,
                                                        "amount": "TZS 40,000",
                                                        "occurred_at": "2026-09-08T14:34:52+03:00"
                                                    }
                                                ],
                                                "refunds": []
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold payments.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"payments.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No payment with that id or reference in this workspace.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/data/tables/{table}/states": {
            "get": {
                "tags": [
                    "Data tables"
                ],
                "operationId": "v3DataTableStates",
                "summary": "Read a table\u2019s status fields and legal transitions",
                "description": "Read state keys and allowed transitions before creating or changing a status value. Every status field includes its initial states and next moves with permission-aware allowed flags. Use ordinary record PATCH to apply a state value; this read does not reserve a transition.",
                "x-permission": "data.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/DataTableId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Status state machines visible to this caller.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/DataTableStates"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "table": {
                                                "id": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                                "name": "Orders",
                                                "slug": "orders"
                                            },
                                            "fields": []
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "Key issuer lacks data.view.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "You do not have permission to perform this action."
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Invalid UUID, unknown table or table hidden from this caller.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Resource not found."
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/automations/events": {
            "get": {
                "tags": [
                    "Automations"
                ],
                "operationId": "v3AutomationEvents",
                "x-permission": "automations.view",
                "x-permission-scope": "controller",
                "summary": "Read the business event log",
                "description": "Read business events newest first in the native {events,has_more,next_before,event_keys} envelope. Requires automations.view. The event_keys catalog declares publisher availability with live; keys marked false do not currently publish. delivered_at records fan-out processing, and delivered_count counts successful dispatch outcomes, including queued webhook/agent jobs whose external work may still be pending. limit defaults to 50 and clamps to 1\u201350. Pass next_before as before for a strict older-than timestamp filter. A full page sets has_more=true without proving another row exists. Invalid before values restart at the newest page. The timestamp cursor has no ID tie-breaker and is not a lossless high-volume export cursor.",
                "parameters": [
                    {
                        "name": "key",
                        "in": "query",
                        "required": false,
                        "description": "Only this event. One of the platform's closed list; anything else is refused with a 422 naming the ones that exist.",
                        "schema": {
                            "type": "string",
                            "example": "record.transitioned"
                        }
                    },
                    {
                        "name": "subject_id",
                        "in": "query",
                        "required": false,
                        "description": "Everything that ever happened to one thing \u2014 a record id, an approval id.",
                        "schema": {
                            "type": "string",
                            "example": "9f1c2d3e-4a5b-4c6d-8e9f-0a1b2c3d4e5f"
                        }
                    },
                    {
                        "name": "before",
                        "in": "query",
                        "required": false,
                        "description": "Read the page older than this timestamp \u2014 the next_before value from the previous page.",
                        "schema": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2026-09-08T09:14:22+03:00"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "How many events to return, 1 to 50.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 50,
                            "default": 50
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The event log, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "events",
                                        "has_more"
                                    ],
                                    "properties": {
                                        "events": {
                                            "type": "array",
                                            "description": "The events, newest first.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The event's id \u2014 a uuid v7, so sorting by it is sorting by time."
                                                    },
                                                    "key": {
                                                        "type": "string",
                                                        "description": "What happened, from the platform's closed list, e.g. record.transitioned.",
                                                        "enum": [
                                                            "record.created",
                                                            "record.updated",
                                                            "record.deleted",
                                                            "record.transitioned",
                                                            "payment.paid",
                                                            "payment.failed",
                                                            "payment.refunded",
                                                            "order.completed",
                                                            "approval.requested",
                                                            "approval.settled",
                                                            "booking.confirmed",
                                                            "ticket.opened",
                                                            "ticket.closed",
                                                            "call.completed",
                                                            "message.received"
                                                        ]
                                                    },
                                                    "label": {
                                                        "type": "string",
                                                        "description": "The same thing in a sentence, e.g. \"A record moved to a new state\"."
                                                    },
                                                    "subject_type": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "What the event is about, e.g. data_record or approval."
                                                    },
                                                    "subject_id": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "The id of that thing, so every event about one record can be read together."
                                                    },
                                                    "payload": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "What happened, in full. For a record event: the table, the record id, the record itself, and the fields that moved."
                                                    },
                                                    "actor": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "Who did it: kind (user, api, mcp, flow, ivr, schedule, system), id and a label."
                                                    },
                                                    "occurred_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "description": "When it happened, not when it was written."
                                                    },
                                                    "delivered_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When the fan-out finished with it. Null means it has not been processed yet."
                                                    },
                                                    "delivered_count": {
                                                        "type": "integer",
                                                        "description": "How many subscriptions acted on it. Zero with a delivered_at means nothing was listening \u2014 the usual reason an automation \"did not run\"."
                                                    }
                                                }
                                            }
                                        },
                                        "has_more": {
                                            "type": "boolean",
                                            "description": "Whether there is an older page."
                                        },
                                        "next_before": {
                                            "type": "string",
                                            "format": "date-time",
                                            "nullable": true,
                                            "description": "Pass this back as before to read the next page."
                                        },
                                        "event_keys": {
                                            "type": "array",
                                            "description": "The closed list of events this platform publishes, so a caller never has to guess one.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "key": {
                                                        "type": "string",
                                                        "description": "The event key."
                                                    },
                                                    "label": {
                                                        "type": "string",
                                                        "description": "What it means, in a sentence."
                                                    },
                                                    "group": {
                                                        "type": "string",
                                                        "description": "Which part of the business it belongs to."
                                                    },
                                                    "subject": {
                                                        "type": "string",
                                                        "description": "What kind of thing the event is about."
                                                    },
                                                    "publisher": {
                                                        "type": "string",
                                                        "description": "Which part of the platform publishes it."
                                                    },
                                                    "live": {
                                                        "type": "boolean",
                                                        "description": "Whether that publisher has shipped yet. A key that is not live is part of the contract but never fires."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "events": [
                                                {
                                                    "id": "01a08270-0000-7000-8000-2a3b4c5d6e7f",
                                                    "key": "record.transitioned",
                                                    "label": "A record moved to a new state",
                                                    "subject_type": "data_record",
                                                    "subject_id": "9f1c2d3e-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
                                                    "payload": {
                                                        "table": {
                                                            "id": "1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7a8b",
                                                            "name": "Orders",
                                                            "slug": "orders"
                                                        },
                                                        "record_id": "9f1c2d3e-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
                                                        "record": {
                                                            "customer": "Asha Mwinyi",
                                                            "status": "paid",
                                                            "total": 45000
                                                        },
                                                        "changes": {
                                                            "status": {
                                                                "from": "confirmed",
                                                                "to": "paid"
                                                            }
                                                        },
                                                        "moved": [
                                                            "status"
                                                        ],
                                                        "source": "ui"
                                                    },
                                                    "actor": {
                                                        "kind": "user",
                                                        "id": 42,
                                                        "label": "Asha Mwinyi"
                                                    },
                                                    "occurred_at": "2026-09-08T09:14:22+03:00",
                                                    "delivered_at": "2026-09-08T09:14:23+03:00",
                                                    "delivered_count": 2
                                                }
                                            ],
                                            "has_more": false,
                                            "next_before": null,
                                            "event_keys": [
                                                {
                                                    "key": "record.transitioned",
                                                    "label": "A record moved to a new state",
                                                    "group": "Records",
                                                    "subject": "data_record",
                                                    "publisher": "Daftari",
                                                    "live": true
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold automations.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"automations.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "The automations module is switched off for this workspace.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The key query parameter named an event this platform does not publish.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Unknown event key. The ones this platform publishes are: record.created, record.updated, record.deleted, record.transitioned, payment.paid, payment.failed, payment.refunded, order.completed, approval.requested, approval.settled, booking.confirmed, ticket.opened, ticket.closed, call.completed, message.received."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/automations/subscriptions": {
            "get": {
                "tags": [
                    "Automations"
                ],
                "operationId": "v3AutomationSubscriptions",
                "x-permission": "automations.view",
                "x-permission-scope": "controller",
                "summary": "List the event subscriptions",
                "description": "What this workspace has arranged to happen when something occurs: start a flow, tell a team, call a URL, or hand it to an assistant. Read this to find out whether an integration is already set up, and to see whether one has been failing \u2014 last_error carries the platform's own sentence, and a subscription that has failed ten times in a row switches itself off and says so. Signing secrets are never returned; signed only says whether a webhook's deliveries carry one. Returns at most 200 rows, ordered by key and label, without pagination. A key filter includes wildcard subscriptions. Intermediate webhook retries do not each increment the consecutive failure counter; the terminal failed delivery does.",
                "parameters": [
                    {
                        "name": "key",
                        "in": "query",
                        "required": false,
                        "description": "Only subscriptions listening for this event. Wildcard subscriptions are always included, because they do listen for it.",
                        "schema": {
                            "type": "string",
                            "example": "payment.paid"
                        }
                    },
                    {
                        "name": "enabled_only",
                        "in": "query",
                        "required": false,
                        "description": "Leave out the ones that are switched off.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The subscriptions on this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "subscriptions"
                                    ],
                                    "properties": {
                                        "subscriptions": {
                                            "type": "array",
                                            "description": "The subscriptions, by event then name.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "integer",
                                                        "description": "The subscription's id."
                                                    },
                                                    "key": {
                                                        "type": "string",
                                                        "description": "The event it listens for, or * for every event."
                                                    },
                                                    "key_label": {
                                                        "type": "string",
                                                        "description": "That event in a sentence."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "enum": [
                                                            "flow",
                                                            "notification",
                                                            "webhook",
                                                            "agent"
                                                        ],
                                                        "description": "What it does when the event happens."
                                                    },
                                                    "target": {
                                                        "type": "string",
                                                        "description": "What it does it to: a flow id, who to tell, a URL, or an assistant id."
                                                    },
                                                    "label": {
                                                        "type": "string",
                                                        "description": "What a person calls it."
                                                    },
                                                    "filter": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "nullable": true,
                                                        "description": "A condition over the event; null means it fires on every one."
                                                    },
                                                    "config": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "nullable": true,
                                                        "description": "Per-kind extras \u2014 a notification's title and body, an assistant's instruction, a flow's variables."
                                                    },
                                                    "signed": {
                                                        "type": "boolean",
                                                        "description": "Whether a webhook's deliveries carry a signature. The secret itself is never returned by this API."
                                                    },
                                                    "enabled": {
                                                        "type": "boolean",
                                                        "description": "Whether it is switched on. Ten failures in a row switch one off."
                                                    },
                                                    "last_fired_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When it last acted on an event."
                                                    },
                                                    "fire_count": {
                                                        "type": "integer",
                                                        "description": "How many times it has acted."
                                                    },
                                                    "last_error": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "Why the last attempt failed, in the platform's own words."
                                                    },
                                                    "last_failed_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When that failure was."
                                                    },
                                                    "failure_count": {
                                                        "type": "integer",
                                                        "description": "How many failures in a row. Any success resets it to zero."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When it was set up."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "subscriptions": [
                                                {
                                                    "id": 7,
                                                    "key": "payment.paid",
                                                    "key_label": "A payment settled",
                                                    "kind": "webhook",
                                                    "target": "https://orders.example.co.tz/hooks/momo",
                                                    "label": "Paid orders to the warehouse",
                                                    "filter": {
                                                        "all": [
                                                            {
                                                                "column": "amount",
                                                                "op": "greater_than",
                                                                "value": 10000
                                                            }
                                                        ]
                                                    },
                                                    "config": null,
                                                    "signed": true,
                                                    "enabled": true,
                                                    "last_fired_at": "2026-09-08T09:14:23+03:00",
                                                    "fire_count": 412,
                                                    "last_error": null,
                                                    "last_failed_at": null,
                                                    "failure_count": 0,
                                                    "created_at": "2026-08-01T11:02:00+03:00"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold automations.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"automations.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "The automations module is switched off for this workspace.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/automations/schedules": {
            "get": {
                "tags": [
                    "Automations"
                ],
                "operationId": "v3AutomationSchedules",
                "x-permission": "automations.view",
                "x-permission-scope": "controller",
                "summary": "List the schedules",
                "description": "Read recurring schedules in the native {schedules:[...]} envelope. Requires automations.view. At most 300 rows are returned, ordered by name, without pagination. kind and enabled_only narrow the list. describes is the readable rhythm; spec retains its timezone and recurrence rules. A null next_run_at can indicate a disabled, exhausted or invalid schedule. last_result describes execution, with optional misfire details; follow any resulting resource reference for final delivery. run_once runs one late occurrence, skip advances without firing missed occurrences, and run_all replays at most 12 missed slots per runner tick. Lateness of up to 90 seconds is within the grace period.",
                "parameters": [
                    {
                        "name": "kind",
                        "in": "query",
                        "required": false,
                        "description": "Only this kind of schedule.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "flow",
                                "report",
                                "record",
                                "call",
                                "message"
                            ],
                            "example": "report"
                        }
                    },
                    {
                        "name": "enabled_only",
                        "in": "query",
                        "required": false,
                        "description": "Leave out the ones that are switched off.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The schedules on this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "schedules"
                                    ],
                                    "properties": {
                                        "schedules": {
                                            "type": "array",
                                            "description": "The schedules, by name.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "id": {
                                                        "type": "string",
                                                        "format": "uuid",
                                                        "description": "The schedule's id."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "What a person calls it."
                                                    },
                                                    "kind": {
                                                        "type": "string",
                                                        "enum": [
                                                            "flow",
                                                            "report",
                                                            "record",
                                                            "call",
                                                            "message"
                                                        ],
                                                        "description": "What it does each time it runs."
                                                    },
                                                    "spec": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "The rhythm: every, unit, at, weekdays, day_of_month, timezone, until, count."
                                                    },
                                                    "describes": {
                                                        "type": "string",
                                                        "description": "The same rhythm as one checkable sentence, e.g. \"Every week on Monday at 09:00 (Africa/Dar_es_Salaam)\"."
                                                    },
                                                    "target": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "What it acts on: a table id, a phone number, a flow id, a contact group id."
                                                    },
                                                    "payload": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "The kind's own arguments \u2014 the export spec, the record to write, the message body."
                                                    },
                                                    "misfire_policy": {
                                                        "type": "string",
                                                        "enum": [
                                                            "run_once",
                                                            "skip",
                                                            "run_all"
                                                        ],
                                                        "description": "What happens to runs missed while the platform was down. run_once fires once and carries on; skip fires not at all; run_all catches up, capped."
                                                    },
                                                    "enabled": {
                                                        "type": "boolean",
                                                        "description": "Whether it runs."
                                                    },
                                                    "next_run_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "The next slot, in UTC. Null when it is switched off or has run out."
                                                    },
                                                    "last_run_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When it last ran."
                                                    },
                                                    "last_result": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "nullable": true,
                                                        "description": "What the last run produced: ok, ref (the export, message or record it made), message, and a misfire block when slots were missed."
                                                    },
                                                    "last_error": {
                                                        "type": "string",
                                                        "nullable": true,
                                                        "description": "Why the last run failed."
                                                    },
                                                    "run_count": {
                                                        "type": "integer",
                                                        "description": "How many times it has run."
                                                    },
                                                    "created_at": {
                                                        "type": "string",
                                                        "format": "date-time",
                                                        "nullable": true,
                                                        "description": "When it was set up."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "schedules": [
                                                {
                                                    "id": "3f2a1b0c-9d8e-4f70-8a1b-2c3d4e5f6a7b",
                                                    "name": "Monday sales report",
                                                    "kind": "report",
                                                    "spec": {
                                                        "every": 1,
                                                        "unit": "weeks",
                                                        "at": "09:00",
                                                        "weekdays": [
                                                            1
                                                        ],
                                                        "timezone": "Africa/Dar_es_Salaam"
                                                    },
                                                    "describes": "Every week on Monday at 09:00 (Africa/Dar_es_Salaam)",
                                                    "target": null,
                                                    "payload": {
                                                        "export": {
                                                            "kind": "records",
                                                            "table_id": "1b2c3d4e-5f60-4718-9a2b-3c4d5e6f7a8b",
                                                            "format": "xlsx"
                                                        },
                                                        "deliver": {
                                                            "via": "email",
                                                            "to": "owner@example.co.tz"
                                                        }
                                                    },
                                                    "misfire_policy": "run_once",
                                                    "enabled": true,
                                                    "next_run_at": "2026-09-14T06:00:00+00:00",
                                                    "last_run_at": "2026-09-07T06:00:00+00:00",
                                                    "last_result": {
                                                        "ok": true,
                                                        "ref": "7a8b9c0d-1e2f-4304-8516-27384950a6b7",
                                                        "message": "Export queued."
                                                    },
                                                    "last_error": null,
                                                    "run_count": 6,
                                                    "created_at": "2026-07-20T08:11:00+03:00"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold automations.view, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"automations.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "The automations module is switched off for this workspace.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/engine/tasks": {
            "post": {
                "tags": [
                    "Agent tasks"
                ],
                "operationId": "engineTasksCreate",
                "summary": "Submit a task to an account agent",
                "description": "Submit a prompt and context to an enabled agent available for API execution. Mode defaults sync; queued mode returns a run for polling. Idempotency-Key reuses the tenant/trigger run for the same fingerprint and conflicts on a changed request. The API ceiling is 60 seconds, reduced by profile/request budgets. A successful HTTP response can contain failed/denied/timed_out domain status.",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Optional stable key for this business request. Same request reuses the run; different fingerprint returns 409. Unlike messaging sends, this endpoint implements request-key deduplication.",
                        "schema": {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 191
                        },
                        "example": "order-1042-summary-v1"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "agent_id": {
                                        "type": "integer",
                                        "description": "Agent ID belonging to this account."
                                    },
                                    "prompt": {
                                        "type": "string",
                                        "description": "Task instruction.",
                                        "maxLength": 20000
                                    },
                                    "context": {
                                        "type": [
                                            "object",
                                            "array",
                                            "null"
                                        ],
                                        "description": "Additional task context.",
                                        "additionalProperties": true,
                                        "items": []
                                    },
                                    "mode": {
                                        "type": "string",
                                        "description": "Wait synchronously or enqueue for polling.",
                                        "enum": [
                                            "sync",
                                            "queued"
                                        ],
                                        "default": "sync"
                                    },
                                    "max_duration_ms": {
                                        "type": "integer",
                                        "description": "Requested maximum duration; cannot extend the API/profile ceiling.",
                                        "minimum": 1
                                    }
                                },
                                "required": [
                                    "agent_id",
                                    "prompt"
                                ]
                            },
                            "examples": {
                                "default": {
                                    "value": {
                                        "agent_id": 42,
                                        "prompt": "Summarize this order and suggest the next action.",
                                        "context": {
                                            "order_reference": "ORD-1042"
                                        },
                                        "mode": "queued",
                                        "max_duration_ms": 30000
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Synchronous outcome; inspect status rather than assuming successful execution.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EngineTaskResult"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "succeeded",
                                            "run_uuid": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                            "output": {
                                                "summary": "Order summary."
                                            },
                                            "denial_reason": null,
                                            "usage": []
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "Accepted for background execution. Poll status_url using the same REST credential.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EngineTaskAccepted"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "queued",
                                            "run_uuid": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                            "execution_state": "queued",
                                            "delivery_state": "none",
                                            "deadline_at": "2030-10-12T06:00:30+00:00",
                                            "status_url": "https://business.momo.tz/api/engine/runs/2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                            "denial_reason": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "REST credential failure.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Invalid API token."
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Suspended/inactive account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Account is suspended."
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "Agent not found in this account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Agent not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Idempotency key already identifies a different request.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EngineAdmissionError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "conflict",
                                            "message": "Idempotency-Key was already used for a different request."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Invalid request fields, or a queued task denied/timed out on submission.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/EngineRequestError"
                                        },
                                        {
                                            "$ref": "#/components/schemas/EngineTaskAccepted"
                                        }
                                    ]
                                },
                                "examples": {
                                    "invalidPrompt": {
                                        "summary": "Request validation failed before a run was created",
                                        "value": {
                                            "message": "The prompt field is required.",
                                            "errors": {
                                                "prompt": [
                                                    "The prompt field is required."
                                                ]
                                            }
                                        }
                                    },
                                    "deniedRun": {
                                        "summary": "Queued submission could not execute",
                                        "value": {
                                            "status": "denied",
                                            "run_uuid": "01953b60-4ce0-7000-8000-000000000001",
                                            "execution_state": "denied",
                                            "delivery_state": "none",
                                            "deadline_at": "2030-10-12T06:01:00+00:00",
                                            "status_url": "https://business.momo.tz/api/engine/runs/01953b60-4ce0-7000-8000-000000000001",
                                            "denial_reason": "surface_disabled"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Pending capacity exceeded. Retry-After is 5 seconds.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EngineAdmissionError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "denied",
                                            "run_uuid": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d",
                                            "denial_reason": "tenant_pending_capacity",
                                            "retryable": true,
                                            "retry_after": 5,
                                            "status_url": "https://business.momo.tz/api/engine/runs/2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d"
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "description": "Seconds to wait before attempting a safe retry.",
                                "schema": {
                                    "type": "integer",
                                    "example": 5
                                }
                            },
                            "Cache-Control": {
                                "description": "Admission response must not be cached.",
                                "schema": {
                                    "type": "string",
                                    "example": "no-store"
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "Temporary ingress contention. Retry-After is 1 second.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EngineAdmissionError"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "busy",
                                            "reason": "ingress_busy",
                                            "message": "Task ingress is busy.",
                                            "retryable": true,
                                            "retry_after": 1
                                        }
                                    }
                                }
                            }
                        },
                        "headers": {
                            "Retry-After": {
                                "description": "Seconds to wait before attempting a safe retry.",
                                "schema": {
                                    "type": "integer",
                                    "example": 1
                                }
                            },
                            "Cache-Control": {
                                "description": "Admission response must not be cached.",
                                "schema": {
                                    "type": "string",
                                    "example": "no-store"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/engine/runs/{uuid}": {
            "get": {
                "tags": [
                    "Agent tasks"
                ],
                "operationId": "engineRunsGet",
                "summary": "Read an agent run, children and trace steps",
                "description": "Tenant-scoped polling and inspection. Response contains run outcome, execution/delivery state, output, model usage, costs, child runs and trace steps. Sent with Cache-Control: no-store. Treat trace arguments/results as sensitive business data.",
                "parameters": [
                    {
                        "name": "uuid",
                        "in": "path",
                        "required": true,
                        "description": "Run UUID returned by task submission.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "2c7e1a9b-3d4f-4a5b-8c6d-7e8f9a0b1c2d"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Run and available trace. Cache-Control: no-store.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/EngineRunDetail"
                                },
                                "example": {
                                    "run": {
                                        "uuid": "01953b60-4ce0-7000-8000-000000000001",
                                        "trigger": "api",
                                        "status": "succeeded",
                                        "execution_state": "succeeded",
                                        "delivery_state": "none",
                                        "deadline_at": "2030-10-12T06:01:00+00:00",
                                        "denial_reason": null,
                                        "output": {
                                            "answer": "The report is ready."
                                        },
                                        "provider": "example-provider",
                                        "model_name": "configured-model",
                                        "prompt_tokens": 120,
                                        "completion_tokens": 45,
                                        "cost_wallet": 0.01,
                                        "cost_currency": "TZS",
                                        "duration_ms": 840,
                                        "created_at": "2030-10-12T06:00:00+00:00"
                                    },
                                    "children": [],
                                    "steps": []
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "REST credential failure.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Invalid API token."
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "Suspended/inactive account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Account is suspended."
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No run with this UUID in the authenticated account.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Run not found."
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/operations/{key}": {
            "post": {
                "tags": [
                    "Operations"
                ],
                "operationId": "v3OperationRun",
                "x-permission": "operations.run",
                "x-permission-scope": "controller",
                "summary": "Run a named operation",
                "description": "Do one of this workspace's named operations and get back what it produced.\n\nSend the values it asks for either as a top-level object or wrapped in `inputs`; both are read. Every value is validated first, by the same rules a chat flow and an assistant are held to, and a refusal names the field and changes nothing \u2014 `status` is then `invalid` and `steps` is empty, which is how you tell \"we did not start\" from \"we started and stopped\".\n\nSet `Idempotency-Key` on anything you might retry. A repeat of a key whose call SUCCEEDED replays the identical response with `X-Idempotent-Replay: 1`, so a request that timed out can be sent again without creating a second booking or a second bill. A key whose call was refused is not spent \u2014 fix the value and send it again under the same key. A key whose run failed part-way replays that failure rather than redoing half of it, because steps before the break really happened.\n\nWhen a step fails part-way, the record writes made before it are undone and `rolled_back` says how many went back, how many were left alone because somebody else had changed them, and how many could not be found. `not_undone` says what stayed done \u2014 a message already sent, money already asked for. Nothing outside the data store is reversible, and this endpoint says so rather than implying otherwise.\n\nAn operation never waits. If one of its steps raises an approval, the answer comes back as soon as the approvers are notified: it means they were asked, not that they said yes.",
                "parameters": [
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The operation's key, in snake_case, as it appears on the Operations page. An unknown key answers 404 \u2014 and so does one belonging to another workspace.",
                        "schema": {
                            "type": "string",
                            "example": "create_booking"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string you choose. A repeat of a key whose call succeeded replays the identical response with X-Idempotent-Replay: 1. A refused call does not spend its key.",
                        "schema": {
                            "type": "string",
                            "example": "booking-2026-09-09-0042"
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "description": "The values the operation asks for. Either wrapped in `inputs` or at the top level.",
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "inputs": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "The values the operation asks for, keyed by its own input names. Leave it out and the top level of the body is read instead."
                                    },
                                    "idempotency_key": {
                                        "type": "string",
                                        "description": "The same thing as the Idempotency-Key header, for clients that cannot set one. The header wins."
                                    }
                                }
                            },
                            "example": {
                                "inputs": {
                                    "customer_phone": "0712345678",
                                    "seats": 2,
                                    "day": "2026-09-14"
                                },
                                "idempotency_key": "booking-2026-09-09-0042"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The operation ran. Every step succeeded and `outputs` is what it promised.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "ok",
                                        "status",
                                        "outputs"
                                    ],
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "description": "True only when every step ran."
                                        },
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "ok",
                                                "failed",
                                                "invalid"
                                            ],
                                            "description": "ok \u2014 it ran. invalid \u2014 the inputs were refused and nothing ran. failed \u2014 a step broke part-way."
                                        },
                                        "run_id": {
                                            "type": "string",
                                            "format": "uuid",
                                            "description": "This run's id. Time-ordered, and what the Operations page's run log is keyed by."
                                        },
                                        "outputs": {
                                            "type": "object",
                                            "additionalProperties": true,
                                            "description": "What the operation promised back \u2014 a booking reference, a record id, an amount."
                                        },
                                        "steps": {
                                            "type": "array",
                                            "description": "One entry per step that ran, in order.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "step": {
                                                        "type": "string",
                                                        "description": "The step's id, as the definition names it."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "What kind of step it was: data_save, rule, payment_intent, send\u2026"
                                                    },
                                                    "ok": {
                                                        "type": "boolean",
                                                        "description": "Whether that step succeeded."
                                                    },
                                                    "ms": {
                                                        "type": "integer",
                                                        "description": "How long that step took, in milliseconds. This is the number that answers \"why was it slow\"."
                                                    },
                                                    "detail": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "What the step produced \u2014 the record it wrote, the rule's answer, the payment reference."
                                                    },
                                                    "not_undone": {
                                                        "type": "string",
                                                        "description": "Present when this step did something a rollback cannot take back."
                                                    }
                                                }
                                            }
                                        },
                                        "replayed": {
                                            "type": "boolean",
                                            "description": "Present and true when this answer was replayed for a repeated idempotency key rather than run again."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "Absent on success. Present on a refusal, carrying the same sentence as error.message for older v3 clients."
                                        }
                                    }
                                },
                                "example": {
                                    "ok": true,
                                    "status": "ok",
                                    "run_id": "0192f3b8-6c2a-7c31-9f2e-5b1c0a7d4e11",
                                    "outputs": {
                                        "booking_ref": "BKG-0042",
                                        "record_id": "9a1c0c7e-1f8c-4a41-9b1e-0d2f7c9b3a55"
                                    },
                                    "steps": [
                                        {
                                            "step": "check_limit",
                                            "type": "rule",
                                            "ok": true,
                                            "ms": 12,
                                            "detail": {
                                                "passed": true,
                                                "value": 2
                                            }
                                        },
                                        {
                                            "step": "booking",
                                            "type": "data_save",
                                            "ok": true,
                                            "ms": 41,
                                            "detail": {
                                                "record_id": "9a1c0c7e-1f8c-4a41-9b1e-0d2f7c9b3a55"
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold operations.run, or the key has no issuer on record.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"operations.run\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No operation with that key in this workspace.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "No operation with that key on this account."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The inputs were refused, or a step failed. `status` says which: `invalid` means nothing ran, `failed` means a step broke and the record writes before it were undone.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "ok": {
                                            "type": "boolean",
                                            "description": "False."
                                        },
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "invalid",
                                                "failed"
                                            ],
                                            "description": "invalid \u2014 the inputs were refused before step one. failed \u2014 a step broke part-way."
                                        },
                                        "run_id": {
                                            "type": "string",
                                            "format": "uuid",
                                            "description": "The run this refusal was recorded against; it is in the run log either way."
                                        },
                                        "outputs": {
                                            "type": "object",
                                            "additionalProperties": true,
                                            "description": "Empty on a refusal: an operation promises nothing it did not finish."
                                        },
                                        "error": {
                                            "type": "object",
                                            "description": "The platform error envelope: a machine code, a sentence a person can act on, and the field at fault.",
                                            "properties": {
                                                "code": {
                                                    "type": "string",
                                                    "description": "validation_error, conflict, not_found, quota_exceeded, rate_limited, temporary_failure, permission_denied, not_supported or provider_failure."
                                                },
                                                "message": {
                                                    "type": "string",
                                                    "description": "What went wrong, written for a person to read."
                                                },
                                                "field": {
                                                    "type": "string",
                                                    "description": "The input or the step at fault."
                                                }
                                            }
                                        },
                                        "rolled_back": {
                                            "type": "object",
                                            "description": "Present on a `failed` run: what the compensating rollback managed to put back.",
                                            "properties": {
                                                "attempted": {
                                                    "type": "integer",
                                                    "description": "How many record writes had inverses to replay."
                                                },
                                                "restored": {
                                                    "type": "integer",
                                                    "description": "How many went back."
                                                },
                                                "conflicts": {
                                                    "type": "integer",
                                                    "description": "How many were left alone because somebody else had changed them since. A rollback never overwrites another person's work."
                                                },
                                                "missing": {
                                                    "type": "integer",
                                                    "description": "How many rows could no longer be found."
                                                },
                                                "failed": {
                                                    "type": "integer",
                                                    "description": "How many inverses could not be applied at all."
                                                },
                                                "not_journalled": {
                                                    "type": "boolean",
                                                    "description": "True when the operation wrote more than the journal holds, so later writes are not reversible."
                                                }
                                            }
                                        },
                                        "not_undone": {
                                            "type": "array",
                                            "description": "What stayed done: a message already sent, money already asked for, an approval already raised. Nothing outside the data store comes back.",
                                            "items": {
                                                "type": "string",
                                                "description": "One sentence per irreversible thing that happened."
                                            }
                                        },
                                        "steps": {
                                            "type": "array",
                                            "description": "The steps that ran before it stopped, with their timing. Empty when the status is `invalid`.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "step": {
                                                        "type": "string",
                                                        "description": "The step's id, as the definition names it."
                                                    },
                                                    "type": {
                                                        "type": "string",
                                                        "description": "What kind of step it was: data_save, rule, payment_intent, send\u2026"
                                                    },
                                                    "ok": {
                                                        "type": "boolean",
                                                        "description": "Whether that step succeeded."
                                                    },
                                                    "ms": {
                                                        "type": "integer",
                                                        "description": "How long that step took, in milliseconds. This is the number that answers \"why was it slow\"."
                                                    },
                                                    "detail": {
                                                        "type": "object",
                                                        "additionalProperties": true,
                                                        "description": "What the step produced \u2014 the record it wrote, the rule's answer, the payment reference."
                                                    },
                                                    "not_undone": {
                                                        "type": "string",
                                                        "description": "Present when this step did something a rollback cannot take back."
                                                    }
                                                }
                                            }
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The same sentence as error.message, for older v3 clients."
                                        }
                                    }
                                },
                                "examples": {
                                    "refused": {
                                        "value": {
                                            "ok": false,
                                            "status": "invalid",
                                            "run_id": "0192f3b8-6c2a-7c31-9f2e-5b1c0a7d4e11",
                                            "outputs": [],
                                            "steps": [],
                                            "error": {
                                                "code": "validation_error",
                                                "message": "Customer phone: That does not look like a phone number. Send it as 0712 345 678.",
                                                "field": "customer_phone"
                                            },
                                            "message": "Customer phone: That does not look like a phone number. Send it as 0712 345 678."
                                        }
                                    },
                                    "failed_partway": {
                                        "value": {
                                            "ok": false,
                                            "status": "failed",
                                            "run_id": "0192f3b8-7a10-7bd2-8c44-2e9f1a6b0c93",
                                            "outputs": [],
                                            "error": {
                                                "code": "conflict",
                                                "message": "There is nothing left to give out just now.",
                                                "field": "seat"
                                            },
                                            "rolled_back": {
                                                "attempted": 1,
                                                "restored": 1,
                                                "conflicts": 0,
                                                "missing": 0,
                                                "failed": 0,
                                                "not_journalled": false
                                            },
                                            "not_undone": [
                                                "A sms message was sent to 255712345678."
                                            ],
                                            "message": "There is nothing left to give out just now."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/products/by-sku/{sku}": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3ProductShowBySku",
                "summary": "Read a product by your own code",
                "description": "The same product as `GET /products/{product}`, addressed by the code your system already knows it by, so a sync never has to keep a map of our numeric ids.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "sku",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 100,
                            "example": "MNG-45W"
                        },
                        "description": "Your own product code \u2014 `sku`, or the older `retailer_id`."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The product.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Product",
                                            "description": "The product record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9301,
                                        "catalogue_id": 42,
                                        "sku": "MNG-45W",
                                        "retailer_id": "MNG-45W",
                                        "meta_product_id": "7766554433",
                                        "name": "Charger Mango 45W",
                                        "description": "USB-C PD, 1 m cable",
                                        "url": "https://shop.example.com/mng45",
                                        "price": 4500000,
                                        "currency": "TZS",
                                        "sale_price": 3900000,
                                        "image_url": "https://cdn.example.com/mng45.jpg",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": "Mango",
                                        "category": "Chargers",
                                        "product_type": "Electronics > Chargers",
                                        "inventory": 12,
                                        "visibility": "published",
                                        "review_status": "approved",
                                        "sync_status": "synced",
                                        "listings": [
                                            {
                                                "platform": "whatsapp",
                                                "state": "synced",
                                                "external_id": "7766554433",
                                                "problem": null,
                                                "review_status": "approved",
                                                "last_synced_at": "2026-09-11T02:00:41+00:00"
                                            }
                                        ],
                                        "last_synced_at": "2026-09-11T02:00:41+00:00",
                                        "created_at": "2026-09-01T08:20:00+00:00",
                                        "updated_at": "2026-09-11T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            },
            "put": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3ProductUpsertBySku",
                "summary": "Create or update a product by your own code",
                "description": "Changes the product with this code, or creates it when there is none \u2014 so a store that has just added an item does not have to know whether we have seen it before. Only the fields you send are touched.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "sku",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 100,
                            "example": "MNG-45W"
                        },
                        "description": "Your own product code \u2014 `sku`, or the older `retailer_id`."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [],
                                "description": "A product. Only a name and a price are required here; an image, a non-zero price and the rest are what individual PLATFORMS require, and a product missing them is stored and reported as `blocked` on that platform rather than refused.",
                                "properties": {
                                    "sku": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Your product code. Left out, the shop issues one."
                                    },
                                    "retailer_id": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "The older name for `sku`."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 200,
                                        "description": "Product name as customers see it."
                                    },
                                    "price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Price in the minor unit of `currency` \u2014 25000 is TZS 250.00 for a 2-decimal currency."
                                    },
                                    "currency": {
                                        "type": "string",
                                        "minLength": 3,
                                        "maxLength": 3,
                                        "description": "ISO 4217 code. Left out, the shop's own currency is used."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 9000,
                                        "description": "Long description."
                                    },
                                    "sale_price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Optional sale price in the minor unit. Ignored when it is higher than `price`."
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Publicly reachable image. Platforms fetch it themselves, so it cannot sit behind a login."
                                    },
                                    "additional_image_urls": {
                                        "type": "array",
                                        "maxItems": 10,
                                        "items": {
                                            "type": "string",
                                            "format": "uri"
                                        },
                                        "description": "Up to ten more images."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "The product page on your own site."
                                    },
                                    "availability": {
                                        "type": "string",
                                        "enum": [
                                            "in stock",
                                            "out of stock",
                                            "preorder",
                                            "available for order",
                                            "discontinued"
                                        ],
                                        "description": "Left out, it is derived from `inventory`: a count of zero means `out of stock` unless the shop allows backorders. Sent explicitly, what you send wins."
                                    },
                                    "condition": {
                                        "type": "string",
                                        "enum": [
                                            "new",
                                            "refurbished",
                                            "used"
                                        ],
                                        "description": "Item condition."
                                    },
                                    "brand": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Brand name. Becomes a brand record on first use."
                                    },
                                    "category": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Category name. Becomes a category record on first use."
                                    },
                                    "product_type": {
                                        "type": "string",
                                        "maxLength": 750,
                                        "description": "Your own taxonomy path."
                                    },
                                    "inventory": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Units on hand."
                                    },
                                    "visibility": {
                                        "type": "string",
                                        "enum": [
                                            "staging",
                                            "published"
                                        ],
                                        "description": "Whether customers may see it."
                                    },
                                    "custom_labels": {
                                        "type": "array",
                                        "maxItems": 5,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Up to five free labels for your own segmentation."
                                    }
                                }
                            },
                            "example": {
                                "inventory": 0,
                                "price": 4200000
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated product.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Product",
                                            "description": "The product record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9301,
                                        "catalogue_id": 42,
                                        "sku": "MNG-45W",
                                        "retailer_id": "MNG-45W",
                                        "meta_product_id": "7766554433",
                                        "name": "Charger Mango 45W",
                                        "description": "USB-C PD, 1 m cable",
                                        "url": "https://shop.example.com/mng45",
                                        "price": 4500000,
                                        "currency": "TZS",
                                        "sale_price": 3900000,
                                        "image_url": "https://cdn.example.com/mng45.jpg",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": "Mango",
                                        "category": "Chargers",
                                        "product_type": "Electronics > Chargers",
                                        "inventory": 12,
                                        "visibility": "published",
                                        "review_status": "approved",
                                        "sync_status": "synced",
                                        "listings": [
                                            {
                                                "platform": "whatsapp",
                                                "state": "synced",
                                                "external_id": "7766554433",
                                                "problem": null,
                                                "review_status": "approved",
                                                "last_synced_at": "2026-09-11T02:00:41+00:00"
                                            }
                                        ],
                                        "last_synced_at": "2026-09-11T02:00:41+00:00",
                                        "created_at": "2026-09-01T08:20:00+00:00",
                                        "updated_at": "2026-09-11T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "201": {
                        "description": "The product did not exist and was created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Product",
                                            "description": "The product record."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9301,
                                        "catalogue_id": 42,
                                        "sku": "MNG-45W",
                                        "retailer_id": "MNG-45W",
                                        "meta_product_id": "7766554433",
                                        "name": "Charger Mango 45W",
                                        "description": "USB-C PD, 1 m cable",
                                        "url": "https://shop.example.com/mng45",
                                        "price": 4500000,
                                        "currency": "TZS",
                                        "sale_price": 3900000,
                                        "image_url": "https://cdn.example.com/mng45.jpg",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": "Mango",
                                        "category": "Chargers",
                                        "product_type": "Electronics > Chargers",
                                        "inventory": 12,
                                        "visibility": "published",
                                        "review_status": "approved",
                                        "sync_status": "synced",
                                        "listings": [
                                            {
                                                "platform": "whatsapp",
                                                "state": "synced",
                                                "external_id": "7766554433",
                                                "problem": null,
                                                "review_status": "approved",
                                                "last_synced_at": "2026-09-11T02:00:41+00:00"
                                            }
                                        ],
                                        "last_synced_at": "2026-09-11T02:00:41+00:00",
                                        "created_at": "2026-09-01T08:20:00+00:00",
                                        "updated_at": "2026-09-11T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3ProductDeleteBySku",
                "summary": "Delete a product by your own code",
                "description": "Takes the product off every platform it is on, then off the shelf.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "sku",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 100,
                            "example": "MNG-45W"
                        },
                        "description": "Your own product code \u2014 `sku`, or the older `retailer_id`."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The product was removed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                },
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The id of the product that was removed."
                                                },
                                                "sku": {
                                                    "type": "string",
                                                    "description": "The code it was known by."
                                                },
                                                "retailer_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The older name for that code."
                                                }
                                            },
                                            "description": "What was removed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "deleted": true,
                                        "id": 9301,
                                        "sku": "MNG-45W",
                                        "retailer_id": "MNG-45W"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/syncs": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueSyncIndex",
                "summary": "List bulk writes",
                "description": "Every bulk write into this catalogue, newest first \u2014 the API, a scheduled feed pull, or a spreadsheet import.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of syncs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/CatalogueSync"
                                                    },
                                                    "description": "The syncs on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "A page of syncs."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 812,
                                                "catalogue_id": 42,
                                                "source": "api",
                                                "mode": "upsert",
                                                "status": "completed",
                                                "idempotency_key": "nightly-2026-09-11",
                                                "received": 2000,
                                                "created": 12,
                                                "updated": 1982,
                                                "unchanged": 0,
                                                "rejected": 6,
                                                "retired": 0,
                                                "platforms": {
                                                    "whatsapp": {
                                                        "synced": 1960,
                                                        "blocked": 34
                                                    }
                                                },
                                                "problems": [
                                                    {
                                                        "sku": "MNG-CABLE",
                                                        "stage": "ingest",
                                                        "reason": "Price must be a whole number of minor units, 0 or more."
                                                    },
                                                    {
                                                        "sku": "MNG-KNIFE",
                                                        "stage": "whatsapp",
                                                        "reason": "WhatsApp needs a product image it can fetch."
                                                    }
                                                ],
                                                "problems_truncated": false,
                                                "error": null,
                                                "started_at": "2026-09-11T02:00:05+00:00",
                                                "finished_at": "2026-09-11T02:00:41+00:00",
                                                "created_at": "2026-09-11T02:00:04+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/syncs/{sync}": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3CatalogueSyncShow",
                "summary": "Read a sync report",
                "description": "What became of one bulk write. `problems[].stage` is the field to read first: `ingest` means the row was not stored at all, and any other value is the name of a platform that stored it but will not show it \u2014 two very different things that both look like \"my product is not live\".",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "sync",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 812
                        },
                        "description": "Sync id, from the batch response."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The sync report.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatalogueSync",
                                            "description": "The sync report."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 812,
                                        "catalogue_id": 42,
                                        "source": "api",
                                        "mode": "upsert",
                                        "status": "completed",
                                        "idempotency_key": "nightly-2026-09-11",
                                        "received": 2000,
                                        "created": 12,
                                        "updated": 1982,
                                        "unchanged": 0,
                                        "rejected": 6,
                                        "retired": 0,
                                        "platforms": {
                                            "whatsapp": {
                                                "synced": 1960,
                                                "blocked": 34
                                            }
                                        },
                                        "problems": [
                                            {
                                                "sku": "MNG-CABLE",
                                                "stage": "ingest",
                                                "reason": "Price must be a whole number of minor units, 0 or more."
                                            },
                                            {
                                                "sku": "MNG-KNIFE",
                                                "stage": "whatsapp",
                                                "reason": "WhatsApp needs a product image it can fetch."
                                            }
                                        ],
                                        "problems_truncated": false,
                                        "error": null,
                                        "started_at": "2026-09-11T02:00:05+00:00",
                                        "finished_at": "2026-09-11T02:00:41+00:00",
                                        "created_at": "2026-09-11T02:00:04+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/inventory": {
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3StockUpdate",
                "summary": "Set stock levels in bulk",
                "description": "The endpoint to call the moment something sells on your own site. Levels are **absolute**, never deltas \u2014 your system is stating what it has, and a delta would drift out of step the first time a message was delivered twice.\n\nAvailability follows the count: unless the shop allows backorders, a level of `0` sets the product to `out of stock` and stock coming back lifts it to `in stock` again. `derived` in the response names every product where that happened. A `discontinued` or `preorder` product is never quietly put back on sale by a delivery arriving.\n\nCodes we do not have come back in `unknown_skus` rather than being ignored, and one push is sent to every platform the shop is on rather than one per product.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "levels"
                                ],
                                "properties": {
                                    "levels": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 5000,
                                        "description": "Up to 5,000 levels. A row needs a code and a whole-number count.",
                                        "items": {
                                            "type": "object",
                                            "required": [
                                                "sku",
                                                "inventory"
                                            ],
                                            "properties": {
                                                "sku": {
                                                    "type": "string",
                                                    "maxLength": 100,
                                                    "description": "Your product code (`retailer_id` also accepted)."
                                                },
                                                "inventory": {
                                                    "type": "integer",
                                                    "minimum": 0,
                                                    "description": "Units on hand, absolute."
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            "example": {
                                "levels": [
                                    {
                                        "sku": "MNG-45W",
                                        "inventory": 0
                                    },
                                    {
                                        "sku": "MNG-20W",
                                        "inventory": 37
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "What the levels changed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "updated": {
                                                    "type": "integer",
                                                    "description": "Products whose count changed."
                                                },
                                                "unchanged": {
                                                    "type": "integer",
                                                    "description": "Products already at that level; nothing was re-published for these."
                                                },
                                                "unknown_skus": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Codes this catalogue does not have."
                                                },
                                                "malformed": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Rows missing a code or a usable count."
                                                },
                                                "derived": {
                                                    "type": "array",
                                                    "description": "Products whose availability changed as a result.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "sku": {
                                                                "type": "string",
                                                                "description": "The product code."
                                                            },
                                                            "availability": {
                                                                "type": "string",
                                                                "description": "What it became."
                                                            }
                                                        }
                                                    }
                                                },
                                                "platforms": {
                                                    "type": "object",
                                                    "additionalProperties": {
                                                        "type": "object",
                                                        "additionalProperties": {
                                                            "type": "integer"
                                                        }
                                                    },
                                                    "description": "Per platform, how many listings ended in each state after the push."
                                                }
                                            },
                                            "description": "What changed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "updated": 2,
                                        "unchanged": 0,
                                        "unknown_skus": [],
                                        "malformed": [],
                                        "derived": [
                                            {
                                                "sku": "MNG-45W",
                                                "availability": "out of stock"
                                            }
                                        ],
                                        "platforms": {
                                            "whatsapp": {
                                                "pending": 2
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3StockIndex",
                "summary": "Read stock levels",
                "description": "On hand, held by pending orders, and the difference \u2014 which is the number that decides whether a customer may buy. A product with `tracked: false` carries no count and is never held back.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "sku",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "example": [
                                "MNG-45W"
                            ]
                        },
                        "description": "Only these product codes."
                    },
                    {
                        "name": "tracked_only",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "boolean",
                            "default": false
                        },
                        "description": "Only products that carry a count."
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of stock levels.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/StockLevel"
                                                    },
                                                    "description": "The rows on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "A page of stock levels."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "sku": "MNG-45W",
                                                "inventory": 12,
                                                "reserved": 2,
                                                "available": 10,
                                                "availability": "in stock",
                                                "tracked": true
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 100,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/products/by-sku/{sku}/movements": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3StockMovements",
                "summary": "Read a product\u2019s stock history",
                "description": "Every event that has ever moved this count, newest first \u2014 who moved it, why, and what the figures became. This is the audit trail behind `inventory` and `reserved`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "sku",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "maxLength": 100,
                            "example": "MNG-45W"
                        },
                        "description": "Your own product code."
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of movements.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/InventoryMovement"
                                                    },
                                                    "description": "The rows on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "A page of movements."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 4411,
                                                "kind": "commit",
                                                "quantity": -2,
                                                "on_hand_after": 10,
                                                "reserved_after": 0,
                                                "order_id": 9182,
                                                "reason": null,
                                                "actor": "whatsapp",
                                                "created_at": "2026-09-11T09:14:02+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 100,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/webhooks/events": {
            "get": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookEvents",
                "summary": "List every event we can send",
                "description": "The whole catalogue, grouped, with a sample payload for each. This is what the dashboard picker shows and what the `event` enum in the delivery schema is generated from, so a name here is by definition one the platform sends.",
                "responses": {
                    "200": {
                        "description": "The event catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "events": {
                                                    "type": "array",
                                                    "description": "One entry per event.",
                                                    "items": {
                                                        "type": "object",
                                                        "properties": {
                                                            "event": {
                                                                "type": "string",
                                                                "description": "The name to subscribe with."
                                                            },
                                                            "group": {
                                                                "type": "string",
                                                                "description": "Family: Messages, Orders, Catalogue, Campaigns, WhatsApp groups, Webhooks."
                                                            },
                                                            "label": {
                                                                "type": "string",
                                                                "description": "Human name."
                                                            },
                                                            "description": {
                                                                "type": "string",
                                                                "description": "When it fires and what to do with it."
                                                            },
                                                            "sample": {
                                                                "type": "object",
                                                                "description": "A complete example body."
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "description": "The event catalogue."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "events": [
                                            {
                                                "event": "message.received",
                                                "group": "Messages",
                                                "label": "A message arrived",
                                                "description": "An inbound message from a customer on any channel.",
                                                "sample": {
                                                    "event": "message.received",
                                                    "message_id": 101,
                                                    "direction": "inbound",
                                                    "sender": "255712345678",
                                                    "recipient": "MyBrand",
                                                    "status": "received",
                                                    "body": "Habari, mna kanga?",
                                                    "media_url": null,
                                                    "channel_type": "whatsapp",
                                                    "timestamp": "2026-09-11T09:14:02+00:00"
                                                }
                                            },
                                            {
                                                "event": "message.sent",
                                                "group": "Messages",
                                                "label": "A message was sent",
                                                "description": "An outbound message was handed to the carrier.",
                                                "sample": {
                                                    "event": "message.sent",
                                                    "message_id": 102,
                                                    "direction": "outbound",
                                                    "sender": "MyBrand",
                                                    "recipient": "255712345678",
                                                    "status": "sent",
                                                    "body": "Ndiyo, tuna kanga.",
                                                    "media_url": null,
                                                    "channel_type": "whatsapp",
                                                    "timestamp": "2026-09-11T09:14:02+00:00"
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/webhooks": {
            "get": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookIndex",
                "summary": "List your receivers",
                "description": "Every endpoint registered on this account, with its health.",
                "responses": {
                    "200": {
                        "description": "Your receivers.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Webhook"
                                                    },
                                                    "description": "The receivers."
                                                }
                                            },
                                            "description": "Your receivers."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 7,
                                                "url": "https://store.example.com/momo",
                                                "events": [
                                                    "order.received",
                                                    "order.status_changed"
                                                ],
                                                "is_active": true,
                                                "paused_at": null,
                                                "paused_reason": null,
                                                "consecutive_failures": 0,
                                                "last_delivered_at": "2026-09-11T09:14:03+00:00",
                                                "created_at": "2026-09-01T08:15:00+00:00",
                                                "updated_at": "2026-09-11T09:14:03+00:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookCreate",
                "summary": "Register a receiver",
                "description": "Subscribe a URL to events. **The response carries `secret` \u2014 the only time it is ever shown.** Store it; your receiver verifies every delivery with it. Needs a key issued by a user with `webhooks.manage`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "A public https address. Private and internal targets are refused, and so is http."
                                    },
                                    "events": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 60,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Event names from `GET /api/v3/webhooks/events`. An unknown name is refused."
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "description": "Switch the receiver on or off. Turning a paused endpoint back on resumes it."
                                    },
                                    "filters": {
                                        "type": "object",
                                        "description": "Narrow which events of a kind reach this receiver. Only `lead` is defined: lead.* events are sent only for leads in these stages, with at least one of these labels, from these channels. An empty or missing list means any.",
                                        "properties": {
                                            "lead": {
                                                "type": "object",
                                                "description": "Filters for lead.* events.",
                                                "properties": {
                                                    "stages": {
                                                        "type": "array",
                                                        "description": "Only leads in these stages.",
                                                        "items": {
                                                            "type": "string",
                                                            "enum": [
                                                                "new",
                                                                "contacted",
                                                                "qualified",
                                                                "opportunity",
                                                                "won",
                                                                "lost",
                                                                "unqualified"
                                                            ]
                                                        }
                                                    },
                                                    "labels": {
                                                        "type": "array",
                                                        "description": "Only leads carrying one of these labels (names).",
                                                        "items": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "channels": {
                                                        "type": "array",
                                                        "description": "Only leads that first came from these channels.",
                                                        "items": {
                                                            "type": "string",
                                                            "enum": [
                                                                "call",
                                                                "whatsapp",
                                                                "sms",
                                                                "messenger",
                                                                "instagram",
                                                                "tiktok",
                                                                "email",
                                                                "comment",
                                                                "form",
                                                                "web",
                                                                "chat",
                                                                "manual",
                                                                "import",
                                                                "api"
                                                            ]
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "headers": {
                                        "type": "object",
                                        "description": "Up to five extra headers sent with every delivery, name \u2192 value \u2014 for example the token your system expects. Replaces the whole set; `{}` removes them. Names Momo sets itself (X-Signature*, X-Event*, X-Delivery-Id, X-Timestamp, Content-Type, Content-Length, Host, User-Agent) are refused. Values are stored encrypted and never shown again.",
                                        "maxProperties": 5,
                                        "additionalProperties": {
                                            "type": "string",
                                            "maxLength": 1024
                                        }
                                    }
                                },
                                "required": [
                                    "url",
                                    "events"
                                ]
                            },
                            "example": {
                                "url": "https://crm.example.co.tz/hooks/momo",
                                "events": [
                                    "lead.created",
                                    "lead.stage_changed",
                                    "lead.updated"
                                ],
                                "filters": {
                                    "lead": {
                                        "stages": [
                                            "qualified",
                                            "opportunity",
                                            "won"
                                        ],
                                        "labels": [
                                            "hot"
                                        ]
                                    }
                                },
                                "headers": {
                                    "Authorization": "Bearer 4f2c9b\u2026"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The receiver, with its secret.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/Webhook"
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "secret": {
                                                            "type": "string",
                                                            "description": "The signing secret. Shown here and never again."
                                                        }
                                                    }
                                                }
                                            ],
                                            "description": "The receiver, with its secret."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 7,
                                        "url": "https://store.example.com/momo",
                                        "events": [
                                            "order.received",
                                            "order.status_changed"
                                        ],
                                        "is_active": true,
                                        "paused_at": null,
                                        "paused_reason": null,
                                        "consecutive_failures": 0,
                                        "last_delivered_at": "2026-09-11T09:14:03+00:00",
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-11T09:14:03+00:00",
                                        "secret": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/webhooks/{webhook}": {
            "get": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookShow",
                "summary": "Read a receiver",
                "description": "One receiver and its health. The secret is not included.",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 7
                        },
                        "description": "Webhook id."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The receiver.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Webhook",
                                            "description": "The receiver."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 7,
                                        "url": "https://store.example.com/momo",
                                        "events": [
                                            "order.received",
                                            "order.status_changed"
                                        ],
                                        "is_active": true,
                                        "paused_at": null,
                                        "paused_reason": null,
                                        "consecutive_failures": 0,
                                        "last_delivered_at": "2026-09-11T09:14:03+00:00",
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-11T09:14:03+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookUpdate",
                "summary": "Change a receiver",
                "description": "Change the URL, the events, or switch it on or off. Setting `is_active: true` on a paused endpoint resumes it.",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 7
                        },
                        "description": "Webhook id."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "A public https address. Private and internal targets are refused, and so is http."
                                    },
                                    "events": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 60,
                                        "items": {
                                            "type": "string"
                                        },
                                        "description": "Event names from `GET /api/v3/webhooks/events`. An unknown name is refused."
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "description": "Switch the receiver on or off. Turning a paused endpoint back on resumes it."
                                    },
                                    "filters": {
                                        "type": "object",
                                        "description": "Narrow which events of a kind reach this receiver. Only `lead` is defined: lead.* events are sent only for leads in these stages, with at least one of these labels, from these channels. An empty or missing list means any.",
                                        "properties": {
                                            "lead": {
                                                "type": "object",
                                                "description": "Filters for lead.* events.",
                                                "properties": {
                                                    "stages": {
                                                        "type": "array",
                                                        "description": "Only leads in these stages.",
                                                        "items": {
                                                            "type": "string",
                                                            "enum": [
                                                                "new",
                                                                "contacted",
                                                                "qualified",
                                                                "opportunity",
                                                                "won",
                                                                "lost",
                                                                "unqualified"
                                                            ]
                                                        }
                                                    },
                                                    "labels": {
                                                        "type": "array",
                                                        "description": "Only leads carrying one of these labels (names).",
                                                        "items": {
                                                            "type": "string"
                                                        }
                                                    },
                                                    "channels": {
                                                        "type": "array",
                                                        "description": "Only leads that first came from these channels.",
                                                        "items": {
                                                            "type": "string",
                                                            "enum": [
                                                                "call",
                                                                "whatsapp",
                                                                "sms",
                                                                "messenger",
                                                                "instagram",
                                                                "tiktok",
                                                                "email",
                                                                "comment",
                                                                "form",
                                                                "web",
                                                                "chat",
                                                                "manual",
                                                                "import",
                                                                "api"
                                                            ]
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "headers": {
                                        "type": "object",
                                        "description": "Up to five extra headers sent with every delivery, name \u2192 value \u2014 for example the token your system expects. Replaces the whole set; `{}` removes them. A header sent with the value `null` keeps the value already stored, so you can change one header without sending the others' secrets again. Names Momo sets itself (X-Signature*, X-Event*, X-Delivery-Id, X-Timestamp, Content-Type, Content-Length, Host, User-Agent) are refused. Values are stored encrypted and never shown again.",
                                        "maxProperties": 5,
                                        "additionalProperties": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "maxLength": 1024
                                        }
                                    }
                                }
                            },
                            "example": {
                                "events": [
                                    "order.received",
                                    "order.status_changed",
                                    "stock.low"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated receiver.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Webhook",
                                            "description": "The updated receiver."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 7,
                                        "url": "https://store.example.com/momo",
                                        "events": [
                                            "order.received",
                                            "order.status_changed"
                                        ],
                                        "is_active": true,
                                        "paused_at": null,
                                        "paused_reason": null,
                                        "consecutive_failures": 0,
                                        "last_delivered_at": "2026-09-11T09:14:03+00:00",
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-11T09:14:03+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookDelete",
                "summary": "Remove a receiver",
                "description": "Stops every delivery to it. The delivery log goes with it.",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 7
                        },
                        "description": "Webhook id."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Removed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                },
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The id that was removed."
                                                }
                                            },
                                            "description": "What was removed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "deleted": true,
                                        "id": 7
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/webhooks/{webhook}/rotate-secret": {
            "post": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookRotateSecret",
                "summary": "Issue a new signing secret",
                "description": "The old secret stops verifying immediately, so update your receiver first and rotate second. The new one is in the response and is never shown again.",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 7
                        },
                        "description": "Webhook id."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The receiver, with its new secret.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/Webhook"
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "secret": {
                                                            "type": "string",
                                                            "description": "The new signing secret. Shown here and never again."
                                                        }
                                                    }
                                                }
                                            ],
                                            "description": "The receiver, with its new secret."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 7,
                                        "url": "https://store.example.com/momo",
                                        "events": [
                                            "order.received",
                                            "order.status_changed"
                                        ],
                                        "is_active": true,
                                        "paused_at": null,
                                        "paused_reason": null,
                                        "consecutive_failures": 0,
                                        "last_delivered_at": "2026-09-11T09:14:03+00:00",
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-11T09:14:03+00:00",
                                        "secret": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/webhooks/{webhook}/deliveries": {
            "get": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookDeliveries",
                "summary": "Read the delivery log",
                "description": "Every delivery to this receiver, newest first: what was sent, how many times, what came back. This is how you find out an endpoint has been failing without waiting for a customer to complain.",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 7
                        },
                        "description": "Webhook id."
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "pending",
                                "delivered",
                                "failed",
                                "skipped"
                            ],
                            "example": "failed"
                        },
                        "description": "Only deliveries in this state."
                    },
                    {
                        "name": "event",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "example": "order.received"
                        },
                        "description": "Only this event."
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date-time",
                            "example": "2026-09-11T00:00:00+00:00"
                        },
                        "description": "Only deliveries created at or after this moment."
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of deliveries.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WebhookDelivery"
                                                    },
                                                    "description": "The deliveries on this page."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "A page of deliveries."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 4410,
                                                "delivery_uid": "dlv_01j9qk3v8x2m7n4p5r6s",
                                                "event": "order.received",
                                                "status": "delivered",
                                                "attempts": 1,
                                                "next_attempt_at": null,
                                                "last_attempt_at": "2026-09-11T09:14:03+00:00",
                                                "delivered_at": "2026-09-11T09:14:03+00:00",
                                                "response_code": 200,
                                                "response_excerpt": "ok",
                                                "error": null,
                                                "replay_of_id": null,
                                                "payload": {
                                                    "event": "order.received",
                                                    "order": {
                                                        "id": 9182,
                                                        "catalogue_id": 42,
                                                        "platform": "whatsapp",
                                                        "status": "pending",
                                                        "needs_attention": false,
                                                        "stock_policy": "external",
                                                        "customer_handle": "255712345678",
                                                        "customer_name": "Asha Mrisho",
                                                        "customer_phone": "255712345678",
                                                        "customer_note": null,
                                                        "lines": [
                                                            {
                                                                "sku": "MNG-45W",
                                                                "name": "Charger Mango 45W",
                                                                "quantity": 1,
                                                                "unit_price_minor": 3900000,
                                                                "line_total_minor": 3900000,
                                                                "currency": "TZS",
                                                                "reserved": 1,
                                                                "stock_short": false,
                                                                "unresolved": false
                                                            }
                                                        ],
                                                        "total_minor": 3900000,
                                                        "currency": "TZS",
                                                        "conversation_id": 771,
                                                        "priced_at": "2026-09-11T09:14:02+00:00",
                                                        "created_at": "2026-09-11T09:14:02+00:00",
                                                        "order_id": 9182,
                                                        "customer_wa_id": "255712345678",
                                                        "total_amount": 3900000,
                                                        "total_currency": "TZS"
                                                    },
                                                    "timestamp": "2026-09-11T09:14:02+00:00"
                                                },
                                                "created_at": "2026-09-11T09:14:02+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 50,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/webhooks/{webhook}/deliveries/{delivery}/replay": {
            "post": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookReplay",
                "summary": "Send a delivery again",
                "description": "Queues a fresh delivery of the same payload with a new delivery id. If the endpoint was paused, this resumes it \u2014 a replay is you saying \"it is fixed, try again\".",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 7
                        },
                        "description": "Webhook id."
                    },
                    {
                        "name": "delivery",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 4410
                        },
                        "description": "Delivery id, from the log."
                    }
                ],
                "responses": {
                    "202": {
                        "description": "The new delivery, queued.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WebhookDelivery",
                                            "description": "The new delivery."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 4411,
                                        "delivery_uid": "dlv_01j9qk4a1b2c3d4e5f6g",
                                        "event": "order.received",
                                        "status": "pending",
                                        "attempts": 0,
                                        "next_attempt_at": null,
                                        "last_attempt_at": "2026-09-11T09:14:03+00:00",
                                        "delivered_at": null,
                                        "response_code": null,
                                        "response_excerpt": null,
                                        "error": null,
                                        "replay_of_id": 4410,
                                        "payload": {
                                            "event": "order.received",
                                            "order": {
                                                "id": 9182,
                                                "catalogue_id": 42,
                                                "platform": "whatsapp",
                                                "status": "pending",
                                                "needs_attention": false,
                                                "stock_policy": "external",
                                                "customer_handle": "255712345678",
                                                "customer_name": "Asha Mrisho",
                                                "customer_phone": "255712345678",
                                                "customer_note": null,
                                                "lines": [
                                                    {
                                                        "sku": "MNG-45W",
                                                        "name": "Charger Mango 45W",
                                                        "quantity": 1,
                                                        "unit_price_minor": 3900000,
                                                        "line_total_minor": 3900000,
                                                        "currency": "TZS",
                                                        "reserved": 1,
                                                        "stock_short": false,
                                                        "unresolved": false
                                                    }
                                                ],
                                                "total_minor": 3900000,
                                                "currency": "TZS",
                                                "conversation_id": 771,
                                                "priced_at": "2026-09-11T09:14:02+00:00",
                                                "created_at": "2026-09-11T09:14:02+00:00",
                                                "order_id": 9182,
                                                "customer_wa_id": "255712345678",
                                                "total_amount": 3900000,
                                                "total_currency": "TZS"
                                            },
                                            "timestamp": "2026-09-11T09:14:02+00:00"
                                        },
                                        "created_at": "2026-09-11T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/feeds": {
            "get": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3FeedIndex",
                "summary": "List a catalogue\u2019s feeds",
                "description": "Every feed URL this shop pulls from, with when each last ran and whether it worked.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The feeds.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/CatalogueFeed"
                                                    },
                                                    "description": "The feeds."
                                                }
                                            },
                                            "description": "The feeds."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 3,
                                                "catalogue_id": 42,
                                                "url": "https://shop.example.com/google-feed.xml",
                                                "schedule": "daily",
                                                "mode": "replace",
                                                "is_active": true,
                                                "mapping": {
                                                    "retailer_id": 0,
                                                    "name": 1,
                                                    "price": 5,
                                                    "availability": 7
                                                },
                                                "last_pulled_at": "2026-09-12T02:00:41+00:00",
                                                "next_pull_at": "2026-09-13T02:00:41+00:00",
                                                "last_sync_id": 812,
                                                "last_error": null,
                                                "consecutive_failures": 0,
                                                "created_at": "2026-09-01T08:15:00+00:00",
                                                "updated_at": "2026-09-12T02:00:41+00:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3FeedCreate",
                "summary": "Register a feed",
                "description": "Point the shop at a product feed. It is pulled at once, and the first pull tells you whether the column mapping was guessed right \u2014 read `last_sync_id`. A feed is one-way, so the shop should be under `stock_policy: external`: the store owns the count and the feed states it.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "The feed address. Google Shopping / Meta XML, or CSV, or JSON \u2014 detected from the content."
                                    },
                                    "schedule": {
                                        "type": "string",
                                        "enum": [
                                            "hourly",
                                            "daily",
                                            "manual"
                                        ],
                                        "default": "daily",
                                        "description": "How often to pull."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "upsert",
                                            "replace"
                                        ],
                                        "default": "replace",
                                        "description": "Whether the feed is the whole catalogue."
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "description": "Switch it on or off. Turning it back on clears the failure count."
                                    },
                                    "mapping": {
                                        "type": [
                                            "object",
                                            "null"
                                        ],
                                        "additionalProperties": {
                                            "type": "integer"
                                        },
                                        "description": "Field key \u2192 column position, to override the guess."
                                    }
                                },
                                "required": [
                                    "url"
                                ]
                            },
                            "example": {
                                "url": "https://shop.example.com/google-feed.xml",
                                "schedule": "daily"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The feed, queued for its first pull.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatalogueFeed",
                                            "description": "The feed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 3,
                                        "catalogue_id": 42,
                                        "url": "https://shop.example.com/google-feed.xml",
                                        "schedule": "daily",
                                        "mode": "replace",
                                        "is_active": true,
                                        "mapping": {
                                            "retailer_id": 0,
                                            "name": 1,
                                            "price": 5,
                                            "availability": 7
                                        },
                                        "last_pulled_at": "2026-09-12T02:00:41+00:00",
                                        "next_pull_at": "2026-09-13T02:00:41+00:00",
                                        "last_sync_id": 812,
                                        "last_error": null,
                                        "consecutive_failures": 0,
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-12T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/feeds/{feed}": {
            "patch": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3FeedUpdate",
                "summary": "Change a feed",
                "description": "Change the URL, schedule, mode or mapping, or switch it on or off. A new URL clears the mapping so it is guessed afresh.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "feed",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 3
                        },
                        "description": "Feed id."
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "The feed address. Google Shopping / Meta XML, or CSV, or JSON \u2014 detected from the content."
                                    },
                                    "schedule": {
                                        "type": "string",
                                        "enum": [
                                            "hourly",
                                            "daily",
                                            "manual"
                                        ],
                                        "default": "daily",
                                        "description": "How often to pull."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "enum": [
                                            "upsert",
                                            "replace"
                                        ],
                                        "default": "replace",
                                        "description": "Whether the feed is the whole catalogue."
                                    },
                                    "is_active": {
                                        "type": "boolean",
                                        "description": "Switch it on or off. Turning it back on clears the failure count."
                                    },
                                    "mapping": {
                                        "type": [
                                            "object",
                                            "null"
                                        ],
                                        "additionalProperties": {
                                            "type": "integer"
                                        },
                                        "description": "Field key \u2192 column position, to override the guess."
                                    }
                                }
                            },
                            "example": {
                                "schedule": "hourly",
                                "is_active": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated feed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatalogueFeed",
                                            "description": "The feed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 3,
                                        "catalogue_id": 42,
                                        "url": "https://shop.example.com/google-feed.xml",
                                        "schedule": "daily",
                                        "mode": "replace",
                                        "is_active": true,
                                        "mapping": {
                                            "retailer_id": 0,
                                            "name": 1,
                                            "price": 5,
                                            "availability": 7
                                        },
                                        "last_pulled_at": "2026-09-12T02:00:41+00:00",
                                        "next_pull_at": "2026-09-13T02:00:41+00:00",
                                        "last_sync_id": 812,
                                        "last_error": null,
                                        "consecutive_failures": 0,
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-12T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3FeedDelete",
                "summary": "Remove a feed",
                "description": "Stops pulling. Products already imported stay.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "feed",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 3
                        },
                        "description": "Feed id."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Removed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                },
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The id that was removed."
                                                }
                                            },
                                            "description": "What was removed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "deleted": true,
                                        "id": 3
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/catalogues/{catalogue}/feeds/{feed}/run": {
            "post": {
                "tags": [
                    "Catalogue"
                ],
                "operationId": "v3FeedRun",
                "summary": "Pull a feed now",
                "description": "Whatever the schedule says. Answers 202; read the outcome from the sync the feed's `last_sync_id` points at once it has run.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "name": "feed",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 3
                        },
                        "description": "Feed id."
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Queued.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CatalogueFeed",
                                            "description": "The feed."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 3,
                                        "catalogue_id": 42,
                                        "url": "https://shop.example.com/google-feed.xml",
                                        "schedule": "daily",
                                        "mode": "replace",
                                        "is_active": true,
                                        "mapping": {
                                            "retailer_id": 0,
                                            "name": 1,
                                            "price": 5,
                                            "availability": 7
                                        },
                                        "last_pulled_at": "2026-09-12T02:00:41+00:00",
                                        "next_pull_at": "2026-09-13T02:00:41+00:00",
                                        "last_sync_id": 812,
                                        "last_error": null,
                                        "consecutive_failures": 0,
                                        "created_at": "2026-09-01T08:15:00+00:00",
                                        "updated_at": "2026-09-12T02:00:41+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flows": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowList",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "List message flows",
                "description": "The workspace's message flows as cards, newest change first. Archived flows are left out unless status=archived (or status=all) asks for them. A key issued with scopes needs flows:read.",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "draft, active, paused, archived, or all.",
                        "schema": {
                            "type": "string",
                            "example": "active"
                        }
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Part of the flow's name.",
                        "schema": {
                            "type": "string",
                            "example": "oda"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The flows and the page.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/Flow"
                                            },
                                            "description": "The flows on this page."
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "Page numbers.",
                                            "properties": {
                                                "current_page": {
                                                    "type": "integer",
                                                    "description": "This page."
                                                },
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Rows per page."
                                                },
                                                "total": {
                                                    "type": "integer",
                                                    "description": "Flows matching."
                                                },
                                                "last_page": {
                                                    "type": "integer",
                                                    "description": "The last page number."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": [
                                                {
                                                    "id": 17,
                                                    "name": "Oda ya chakula",
                                                    "description": "Takes a food order and collects payment.",
                                                    "status": "active",
                                                    "priority": 10,
                                                    "channels": [
                                                        "whatsapp"
                                                    ],
                                                    "version": 42,
                                                    "has_unpublished_changes": false,
                                                    "published_version": 3,
                                                    "published_at": "2026-09-12T09:14:02+03:00",
                                                    "node_count": 18,
                                                    "triggers": [
                                                        {
                                                            "type": "keyword",
                                                            "value": "oda",
                                                            "values": [
                                                                "oda",
                                                                "order"
                                                            ]
                                                        }
                                                    ],
                                                    "keywords": [
                                                        "oda",
                                                        "order"
                                                    ],
                                                    "created_at": "2026-08-30T10:00:00+03:00",
                                                    "updated_at": "2026-09-12T09:14:02+03:00"
                                                }
                                            ],
                                            "meta": {
                                                "current_page": 1,
                                                "per_page": 25,
                                                "total": 1,
                                                "last_page": 1
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "An unknown status.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Unknown status \"live\". One of: draft, active, paused, archived."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flows/{flow}": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowShow",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "Read one flow",
                "description": "One flow's card; include=definition adds the draft graph with secrets redacted. The `version` on the card is what a publish must send back as expected_version.",
                "parameters": [
                    {
                        "name": "flow",
                        "in": "path",
                        "required": true,
                        "description": "The flow id.",
                        "schema": {
                            "type": "integer",
                            "example": 17
                        }
                    },
                    {
                        "name": "include",
                        "in": "query",
                        "required": false,
                        "description": "Comma-separated extras: definition.",
                        "schema": {
                            "type": "string",
                            "example": "definition"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The flow.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/Flow"
                                                }
                                            ],
                                            "description": "The flow."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "id": 17,
                                                "name": "Oda ya chakula",
                                                "description": "Takes a food order and collects payment.",
                                                "status": "active",
                                                "priority": 10,
                                                "channels": [
                                                    "whatsapp"
                                                ],
                                                "version": 42,
                                                "has_unpublished_changes": false,
                                                "published_version": 3,
                                                "published_at": "2026-09-12T09:14:02+03:00",
                                                "node_count": 18,
                                                "triggers": [
                                                    {
                                                        "type": "keyword",
                                                        "value": "oda",
                                                        "values": [
                                                            "oda",
                                                            "order"
                                                        ]
                                                    }
                                                ],
                                                "keywords": [
                                                    "oda",
                                                    "order"
                                                ],
                                                "created_at": "2026-08-30T10:00:00+03:00",
                                                "updated_at": "2026-09-12T09:14:02+03:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flows/{flow}/publish": {
            "post": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowPublish",
                "x-permission": "flows.publish",
                "x-permission-scope": "controller",
                "summary": "Publish the draft",
                "description": "Makes the draft live for real customers, after the same validation, scenario tests and go-live readiness checks the builder runs. A draft that equals what is live answers unchanged:true and mints nothing. Needs the flows:publish scope on a scoped key.",
                "parameters": [
                    {
                        "name": "flow",
                        "in": "path",
                        "required": true,
                        "description": "The flow id.",
                        "schema": {
                            "type": "integer",
                            "example": 17
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "expected_version"
                                ],
                                "properties": {
                                    "expected_version": {
                                        "type": "integer",
                                        "description": "The draft version you read on the flow card. A draft somebody changed since answers 409 rather than publishing a graph nobody checked."
                                    }
                                }
                            },
                            "example": {
                                "expected_version": 42
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Published, or nothing to publish.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "What happened.",
                                            "properties": {
                                                "published": {
                                                    "type": "boolean",
                                                    "description": "A new version went live."
                                                },
                                                "unchanged": {
                                                    "type": "boolean",
                                                    "description": "The draft equalled the live version; nothing was minted."
                                                },
                                                "version_number": {
                                                    "type": "integer",
                                                    "nullable": true,
                                                    "description": "The version now live."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "The flow's status after the publish."
                                                },
                                                "issues": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/FlowIssue"
                                                    },
                                                    "description": "Warnings that did not block."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "published": true,
                                                "unchanged": false,
                                                "version_number": 4,
                                                "status": "active",
                                                "issues": []
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The draft moved: expected_version is not the draft's version.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "The draft is at version 43, not 42. Read the flow again and publish with the version it answers."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Refused: graph errors, failed scenario tests or readiness blockers. `issues` names each.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"error\"."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "What to do."
                                        },
                                        "issues": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/FlowIssue"
                                            },
                                            "description": "Every finding, errors and warnings."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Nothing went live. Fix the issues and publish again; a `readiness:*` issue is an account setting fixed at its fix_href.",
                                            "issues": [
                                                {
                                                    "level": "error",
                                                    "node_id": null,
                                                    "field": null,
                                                    "code": "readiness:whatsapp_channel",
                                                    "message": "No WhatsApp number is connected to this workspace, so the flow has nothing to speak from.",
                                                    "fix_href": "/app/accounts"
                                                }
                                            ]
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.publish, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.publish\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flows/{flow}/export": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowExport",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "Export a flow as a bundle",
                "description": "The flow as a marketplace bundle \u2014 the same file the builder's Export menu downloads and its Import reads. Workspace-specific references (tables, profiles, templates) come out as placeholders the importer fills.",
                "parameters": [
                    {
                        "name": "flow",
                        "in": "path",
                        "required": true,
                        "description": "The flow id.",
                        "schema": {
                            "type": "integer",
                            "example": 17
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The bundle.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "additionalProperties": true,
                                    "description": "A flow bundle: format, version, exported_at, the artifacts (the flow and what it carries), and the workspace-specific things an import must supply under requires."
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "format": "momo.marketplace.bundle",
                                            "version": 1,
                                            "exported_at": "2026-09-12T09:14:02+03:00",
                                            "artifacts": [
                                                {
                                                    "kind": "flow",
                                                    "name": "Oda ya chakula",
                                                    "definition": {
                                                        "nodes": []
                                                    }
                                                }
                                            ],
                                            "requires": []
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flows/{flow}/sessions": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowSessionList",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "List a flow's sessions",
                "description": "This flow's sessions, newest first, with the support filters. Cursor-paginated: pass meta.next_cursor as cursor for the next page. No variables ride a list row.",
                "parameters": [
                    {
                        "name": "flow",
                        "in": "path",
                        "required": true,
                        "description": "The flow id.",
                        "schema": {
                            "type": "integer",
                            "example": 17
                        }
                    },
                    {
                        "name": "phone",
                        "in": "query",
                        "required": false,
                        "description": "The customer's phone in any shape (0712\u2026, 255712\u2026, +255712\u2026); matched exactly against the stored identifier.",
                        "schema": {
                            "type": "string",
                            "example": "255712345678"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "One session status.",
                        "schema": {
                            "type": "string",
                            "example": "waiting"
                        }
                    },
                    {
                        "name": "outcome",
                        "in": "query",
                        "required": false,
                        "description": "One outcome word (in_progress, completed, abandoned, handed_over, failed, expired, cancelled, ended_by_operator).",
                        "schema": {
                            "type": "string",
                            "example": "completed"
                        }
                    },
                    {
                        "name": "node",
                        "in": "query",
                        "required": false,
                        "description": "Sessions on this step.",
                        "schema": {
                            "type": "string",
                            "example": "ask_name"
                        }
                    },
                    {
                        "name": "ended_reason",
                        "in": "query",
                        "required": false,
                        "description": "The runtime's ended reason.",
                        "schema": {
                            "type": "string",
                            "example": "timeout"
                        }
                    },
                    {
                        "name": "version",
                        "in": "query",
                        "required": false,
                        "description": "Sessions pinned to this published version id.",
                        "schema": {
                            "type": "integer",
                            "example": 91
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "Started on or after this day (YYYY-MM-DD). `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself).",
                        "schema": {
                            "type": "string",
                            "example": "2026-09-01"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "Started on or before this day (YYYY-MM-DD).",
                        "schema": {
                            "type": "string",
                            "example": "2026-09-12"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Rows per page, at most 100.",
                        "schema": {
                            "type": "integer",
                            "default": 25
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "description": "The next_cursor of the previous page.",
                        "schema": {
                            "type": "string",
                            "example": "eyJtZXNzYWdlX2Zsb3dfc2Vzc2lvbnMuaWQiOjUxMTksIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The sessions.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/FlowSession"
                                            },
                                            "description": "The sessions, newest first."
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "Cursor paging.",
                                            "properties": {
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Rows per page."
                                                },
                                                "next_cursor": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "Pass as cursor for the next page; null on the last."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": [
                                                {
                                                    "id": 5120,
                                                    "flow_id": 17,
                                                    "flow_name": "Oda ya chakula",
                                                    "flow_version": 3,
                                                    "conversation_id": 771,
                                                    "contact_id": 2201,
                                                    "contact_name": "Asha Mrisho",
                                                    "contact_identifier": "255712345678",
                                                    "trigger": "inbound",
                                                    "status": "completed",
                                                    "outcome": "completed",
                                                    "ended_reason": "completed",
                                                    "node_id": "done",
                                                    "awaiting": null,
                                                    "turns": 6,
                                                    "resume_at": null,
                                                    "expires_at": null,
                                                    "started_at": "2026-09-12T09:01:12+03:00",
                                                    "ended_at": "2026-09-12T09:14:02+03:00"
                                                }
                                            ],
                                            "meta": {
                                                "per_page": 25,
                                                "next_cursor": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowSessionStart",
                "x-permission": "flows.edit",
                "x-permission-scope": "controller",
                "summary": "Start a flow for a customer",
                "description": "Queues the live flow on an existing WhatsApp conversation \u2014 by the customer's phone or the conversation id \u2014 with optional starting variables. Answers 202: the session appears once the runner takes its first step, so read the sessions list or subscribe to the flow.session.started webhook. A thread a person has silenced is respected. Needs flows:write on a scoped key.",
                "parameters": [
                    {
                        "name": "flow",
                        "in": "path",
                        "required": true,
                        "description": "The flow id.",
                        "schema": {
                            "type": "integer",
                            "example": 17
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "phone": {
                                        "type": "string",
                                        "description": "The customer's WhatsApp number in any shape. Required unless conversation_id is given."
                                    },
                                    "conversation_id": {
                                        "type": "integer",
                                        "description": "The inbox conversation to start on. Required unless phone is given."
                                    },
                                    "variables": {
                                        "type": "object",
                                        "additionalProperties": true,
                                        "description": "Up to 32 starting variables (strings, numbers, booleans), readable in the flow as {{name}}. Names are letters, digits and underscores."
                                    }
                                }
                            },
                            "example": {
                                "phone": "255712345678",
                                "variables": {
                                    "order_ref": "ORD-2026-0091"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Queued.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The start, queued.",
                                            "properties": {
                                                "queued": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                },
                                                "flow_id": {
                                                    "type": "integer",
                                                    "description": "The flow."
                                                },
                                                "conversation_id": {
                                                    "type": "integer",
                                                    "description": "The conversation it starts on."
                                                },
                                                "contact_identifier": {
                                                    "type": "string",
                                                    "description": "The customer's stored identifier."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "queued": true,
                                                "flow_id": 17,
                                                "conversation_id": 771,
                                                "contact_identifier": "255712345678"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The flow is not live, no conversation with that customer exists, or a variable is not allowed.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This flow is not live: publish it (and resume it if paused) before starting it for a customer."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.edit, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.edit\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flow-sessions": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowSessionFind",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "Find sessions by customer",
                "description": "Sessions across every flow, found by the customer's phone (or narrowed to one flow with `flow`). The same filters and cursor as a flow's session list.",
                "parameters": [
                    {
                        "name": "phone",
                        "in": "query",
                        "required": false,
                        "description": "The customer's phone in any shape (0712\u2026, 255712\u2026, +255712\u2026); matched exactly against the stored identifier.",
                        "schema": {
                            "type": "string",
                            "example": "255712345678"
                        }
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "One session status.",
                        "schema": {
                            "type": "string",
                            "example": "waiting"
                        }
                    },
                    {
                        "name": "outcome",
                        "in": "query",
                        "required": false,
                        "description": "One outcome word (in_progress, completed, abandoned, handed_over, failed, expired, cancelled, ended_by_operator).",
                        "schema": {
                            "type": "string",
                            "example": "completed"
                        }
                    },
                    {
                        "name": "node",
                        "in": "query",
                        "required": false,
                        "description": "Sessions on this step.",
                        "schema": {
                            "type": "string",
                            "example": "ask_name"
                        }
                    },
                    {
                        "name": "ended_reason",
                        "in": "query",
                        "required": false,
                        "description": "The runtime's ended reason.",
                        "schema": {
                            "type": "string",
                            "example": "timeout"
                        }
                    },
                    {
                        "name": "version",
                        "in": "query",
                        "required": false,
                        "description": "Sessions pinned to this published version id.",
                        "schema": {
                            "type": "integer",
                            "example": 91
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "Started on or after this day (YYYY-MM-DD). `GET /api/v3/whatsapp/accounts` lists the accounts and their numbers (`phone_numbers[].id`, or the number itself).",
                        "schema": {
                            "type": "string",
                            "example": "2026-09-01"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "Started on or before this day (YYYY-MM-DD).",
                        "schema": {
                            "type": "string",
                            "example": "2026-09-12"
                        }
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Rows per page, at most 100.",
                        "schema": {
                            "type": "integer",
                            "default": 25
                        }
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "description": "The next_cursor of the previous page.",
                        "schema": {
                            "type": "string",
                            "example": "eyJtZXNzYWdlX2Zsb3dfc2Vzc2lvbnMuaWQiOjUxMTksIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0"
                        }
                    },
                    {
                        "name": "flow",
                        "in": "query",
                        "required": false,
                        "description": "Narrow to one flow id.",
                        "schema": {
                            "type": "integer",
                            "example": 17
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The sessions.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data",
                                        "meta"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/FlowSession"
                                            },
                                            "description": "The sessions, newest first."
                                        },
                                        "meta": {
                                            "type": "object",
                                            "description": "Cursor paging.",
                                            "properties": {
                                                "per_page": {
                                                    "type": "integer",
                                                    "description": "Rows per page."
                                                },
                                                "next_cursor": {
                                                    "type": "string",
                                                    "nullable": true,
                                                    "description": "Pass as cursor for the next page; null on the last."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": [
                                                {
                                                    "id": 5120,
                                                    "flow_id": 17,
                                                    "flow_name": "Oda ya chakula",
                                                    "flow_version": 3,
                                                    "conversation_id": 771,
                                                    "contact_id": 2201,
                                                    "contact_name": "Asha Mrisho",
                                                    "contact_identifier": "255712345678",
                                                    "trigger": "inbound",
                                                    "status": "completed",
                                                    "outcome": "completed",
                                                    "ended_reason": "completed",
                                                    "node_id": "done",
                                                    "awaiting": null,
                                                    "turns": 6,
                                                    "resume_at": null,
                                                    "expires_at": null,
                                                    "started_at": "2026-09-12T09:01:12+03:00",
                                                    "ended_at": "2026-09-12T09:14:02+03:00"
                                                }
                                            ],
                                            "meta": {
                                                "per_page": 25,
                                                "next_cursor": null
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Neither a phone nor a flow was given.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Give a `phone` to find a customer's sessions, or a `flow` id."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flow-sessions/{session}": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowSessionShow",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "Read one session and its trace",
                "description": "The session card and its step-by-step trace, redacted. `variables` is the session's variable bag ONLY for a key whose issuer holds flows.sessions.pii (the same line the app draws), and that read is written to the audit log; otherwise it is null.",
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session id.",
                        "schema": {
                            "type": "integer",
                            "example": 5120
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The session, its trace and \u2014 when permitted \u2014 its variables.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The session in full.",
                                            "properties": {
                                                "session": {
                                                    "allOf": [
                                                        {
                                                            "$ref": "#/components/schemas/FlowSession"
                                                        }
                                                    ],
                                                    "description": "The session card."
                                                },
                                                "steps": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/FlowSessionStep"
                                                    },
                                                    "description": "The trace, oldest first, at most 1000 rows."
                                                },
                                                "variables": {
                                                    "type": "object",
                                                    "additionalProperties": true,
                                                    "nullable": true,
                                                    "description": "The variable bag, redacted, or null when the key may not read it."
                                                },
                                                "exported_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When this read happened."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "session": {
                                                    "id": 5120,
                                                    "flow_id": 17,
                                                    "flow_name": "Oda ya chakula",
                                                    "flow_version": 3,
                                                    "conversation_id": 771,
                                                    "contact_id": 2201,
                                                    "contact_name": "Asha Mrisho",
                                                    "contact_identifier": "255712345678",
                                                    "trigger": "inbound",
                                                    "status": "completed",
                                                    "outcome": "completed",
                                                    "ended_reason": "completed",
                                                    "node_id": "done",
                                                    "awaiting": null,
                                                    "turns": 6,
                                                    "resume_at": null,
                                                    "expires_at": null,
                                                    "started_at": "2026-09-12T09:01:12+03:00",
                                                    "ended_at": "2026-09-12T09:14:02+03:00"
                                                },
                                                "steps": [
                                                    {
                                                        "seq": 3,
                                                        "node_id": "ask_name",
                                                        "node_kind": "ask_text",
                                                        "kind": "awaited",
                                                        "payload": {
                                                            "kind": "text"
                                                        },
                                                        "duration_ms": 12,
                                                        "at": "2026-09-12T09:14:02+03:00"
                                                    }
                                                ],
                                                "variables": null,
                                                "exported_at": "2026-09-12T09:14:02+03:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flow-sessions/{session}/export": {
            "get": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowSessionExport",
                "x-permission": "flows.view",
                "x-permission-scope": "controller",
                "summary": "Download a session's trace as CSV",
                "description": "One row per step: seq, at, node_id, node_kind, kind, detail (JSON), duration_ms. Never carries variables.",
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session id.",
                        "schema": {
                            "type": "integer",
                            "example": 5120
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The CSV.",
                        "content": {
                            "text/csv": {
                                "schema": {
                                    "type": "string",
                                    "description": "CSV text."
                                },
                                "example": "seq,at,node_id,node_kind,kind,detail,duration_ms\n1,2026-09-12T09:01:12+03:00,hi,send_text,entered,{},3\n"
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.view, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.view\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/flow-sessions/{session}/end": {
            "post": {
                "tags": [
                    "Flows"
                ],
                "operationId": "v3FlowSessionEnd",
                "x-permission": "flows.edit",
                "x-permission-scope": "controller",
                "summary": "End a live session",
                "description": "Ends a running or waiting session as an operator would; the conversation goes back to the inbox. notify_customer sends the customer one line saying a person will continue. A session already over answers 409. Needs flows:write on a scoped key.",
                "parameters": [
                    {
                        "name": "session",
                        "in": "path",
                        "required": true,
                        "description": "The session id.",
                        "schema": {
                            "type": "integer",
                            "example": 5120
                        }
                    }
                ],
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "notify_customer": {
                                        "type": "boolean",
                                        "description": "Tell the customer a person will continue. Default false."
                                    }
                                }
                            },
                            "example": {
                                "notify_customer": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Ended.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "data"
                                    ],
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "description": "The result.",
                                            "properties": {
                                                "ended": {
                                                    "type": "boolean",
                                                    "description": "True: it was live and is now cancelled."
                                                },
                                                "message": {
                                                    "type": "string",
                                                    "description": "One sentence."
                                                },
                                                "session": {
                                                    "allOf": [
                                                        {
                                                            "$ref": "#/components/schemas/FlowSession"
                                                        }
                                                    ],
                                                    "description": "The session after the end."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "ended": true,
                                                "message": "The session was ended.",
                                                "session": {
                                                    "status": "cancelled",
                                                    "outcome": "ended_by_operator",
                                                    "id": 5120,
                                                    "flow_id": 17,
                                                    "flow_name": "Oda ya chakula",
                                                    "flow_version": 3,
                                                    "conversation_id": 771,
                                                    "contact_id": 2201,
                                                    "contact_name": "Asha Mrisho",
                                                    "contact_identifier": "255712345678",
                                                    "trigger": "inbound",
                                                    "ended_reason": "completed",
                                                    "node_id": "done",
                                                    "awaiting": null,
                                                    "turns": 6,
                                                    "resume_at": null,
                                                    "expires_at": null,
                                                    "started_at": "2026-09-12T09:01:12+03:00",
                                                    "ended_at": "2026-09-12T09:14:02+03:00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No such flow or session in this workspace. Another workspace's answers 404, never 403.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "Resource not found."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The session had already ended.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "data": {
                                            "type": "object",
                                            "additionalProperties": true,
                                            "description": "The same shape as 200 with ended:false."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "data": {
                                                "ended": false,
                                                "message": "That session had already ended.",
                                                "session": {
                                                    "id": 5120,
                                                    "flow_id": 17,
                                                    "flow_name": "Oda ya chakula",
                                                    "flow_version": 3,
                                                    "conversation_id": 771,
                                                    "contact_id": 2201,
                                                    "contact_name": "Asha Mrisho",
                                                    "contact_identifier": "255712345678",
                                                    "trigger": "inbound",
                                                    "status": "completed",
                                                    "outcome": "completed",
                                                    "ended_reason": "completed",
                                                    "node_id": "done",
                                                    "awaiting": null,
                                                    "turns": 6,
                                                    "resume_at": null,
                                                    "expires_at": null,
                                                    "started_at": "2026-09-12T09:01:12+03:00",
                                                    "ended_at": "2026-09-12T09:14:02+03:00"
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "description": "The key's issuer does not hold flows.edit, the key has no issuer on record, or the key was issued without the scope this call needs.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "status": "error",
                                            "message": "This API key was issued by a user without the \"flows.edit\" permission."
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates": {
            "get": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateList",
                "summary": "List templates",
                "description": "WhatsApp templates in this workspace, newest first, with their Meta review status. Archived rows are left out unless `status=archived` or `status=all`. `updated_since` makes an incremental mirror cheap: it returns rows whose local record changed after that time, which includes every status move.",
                "x-permission": "communications.templates.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "waba_id",
                        "in": "query",
                        "required": false,
                        "description": "Only templates on this WhatsApp Business Account. `GET /api/v3/whatsapp/accounts` lists them (`waba_id`).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "102290129340398"
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Local state. Omit for everything but archived; `all` includes archived.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "active",
                                "archived",
                                "all"
                            ]
                        },
                        "example": "active"
                    },
                    {
                        "name": "whatsapp_status",
                        "in": "query",
                        "required": false,
                        "description": "Meta's review status.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "pending",
                                "in_review",
                                "approved",
                                "rejected",
                                "disabled",
                                "paused"
                            ]
                        },
                        "example": "approved"
                    },
                    {
                        "name": "category",
                        "in": "query",
                        "required": false,
                        "description": "Meta category.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "marketing",
                                "utility",
                                "authentication"
                            ]
                        },
                        "example": "utility"
                    },
                    {
                        "name": "language",
                        "in": "query",
                        "required": false,
                        "description": "Language code, exact.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "sw"
                    },
                    {
                        "name": "name",
                        "in": "query",
                        "required": false,
                        "description": "Template name, exact \u2014 every language of it.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "order_shipped"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Free text over name, display name and body.",
                        "schema": {
                            "type": "string",
                            "maxLength": 120
                        },
                        "example": "oda"
                    },
                    {
                        "name": "updated_since",
                        "in": "query",
                        "required": false,
                        "description": "Only rows changed at or after this ISO-8601 time.",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "example": "2026-09-12T00:00:00Z"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of templates.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "The page of templates.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppTemplateSummary"
                                                    }
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "A page of templates."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 418,
                                                "name": "order_shipped",
                                                "display_name": "Order shipped",
                                                "language": "sw",
                                                "category": "utility",
                                                "status": "active",
                                                "whatsapp_status": "in_review",
                                                "approved": false,
                                                "sendable": false,
                                                "rejection_reason": null,
                                                "whatsapp_business_account_id": "102290129340398",
                                                "whatsapp_template_id": "1189456212345678",
                                                "quality_rating": null,
                                                "parameter_format": "POSITIONAL",
                                                "variables": [
                                                    "1",
                                                    "2"
                                                ],
                                                "body": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                                "last_synced_at": "2026-09-13T09:14:02+00:00",
                                                "created_at": "2026-09-13T09:14:02+00:00",
                                                "updated_at": "2026-09-13T09:14:02+00:00"
                                            },
                                            {
                                                "id": 417,
                                                "name": "karibu",
                                                "display_name": "Order shipped",
                                                "language": "en",
                                                "category": "marketing",
                                                "status": "active",
                                                "whatsapp_status": "approved",
                                                "approved": true,
                                                "sendable": true,
                                                "rejection_reason": null,
                                                "whatsapp_business_account_id": "102290129340398",
                                                "whatsapp_template_id": "1189456200000417",
                                                "quality_rating": "GREEN",
                                                "parameter_format": "POSITIONAL",
                                                "variables": [
                                                    "1"
                                                ],
                                                "body": "Welcome to Amina, {{1}}!",
                                                "last_synced_at": "2026-09-13T09:14:02+00:00",
                                                "created_at": "2026-09-13T09:14:02+00:00",
                                                "updated_at": "2026-09-13T09:14:02+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 2,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateCreate",
                "summary": "Create a template and submit it for review",
                "description": "Creates the template on the chosen WhatsApp Business Account and \u2014 unless `submit` is false \u2014 submits it to Meta for review inside this request. The answer is always 201 with the template; read `whatsapp_status` for Meta's verdict: `in_review` (or `approved` outright) with a `whatsapp_template_id`, or `rejected` with Meta's own words in `rejection_reason` (a bad body, a name it will not take, a token without the permission). Only when Meta cannot be reached is the submission queued to retry; `submission.queued` says so and the row stays `pending`.\n\nDescribe the content either way: `components` in WhatsApp's own shape (everything Meta supports \u2014 media headers, carousels, limited-time offers, copy-code and flow buttons, named parameters), or the flat fields `body`, `header_text`, `footer`, `buttons`, `variable_samples` for the common case. Meta needs a sample value for every placeholder; with the flat fields, supply them in `variable_samples`.\n\nA name is one template per language: `order_shipped` in `sw` and in `en` are two rows, each reviewed on its own. The same name and language again answers 409.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "requestBody": {
                    "description": "The template.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WhatsAppTemplateWriteRequest"
                            },
                            "examples": {
                                "flat": {
                                    "summary": "Flat fields \u2014 the common case",
                                    "value": {
                                        "name": "order_shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "display_name": "Order shipped",
                                        "body": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                        "header_text": "Oda {{1}}",
                                        "footer": "Duka la Amina",
                                        "buttons": [
                                            {
                                                "type": "url",
                                                "text": "Fuatilia",
                                                "url": "https://amina.co.tz/track/{{1}}",
                                                "example": "ORD-1042"
                                            }
                                        ],
                                        "variable_samples": {
                                            "1": "Asha",
                                            "2": "ORD-1042"
                                        }
                                    }
                                },
                                "components": {
                                    "summary": "WhatsApp's own components \u2014 every feature",
                                    "value": {
                                        "name": "ofa_ijumaa",
                                        "language": "sw",
                                        "category": "marketing",
                                        "waba_id": "102290129340398",
                                        "components": [
                                            {
                                                "type": "HEADER",
                                                "format": "IMAGE",
                                                "example": {
                                                    "header_handle": [
                                                        "4::aW1hZ2UvcG5n:ARZ\u2026"
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "BODY",
                                                "text": "Ofa ya {{1}}: punguzo la {{2}} hadi {{3}}.",
                                                "example": {
                                                    "body_text": [
                                                        [
                                                            "Ijumaa",
                                                            "20%",
                                                            "30 Sept"
                                                        ]
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "FOOTER",
                                                "text": "Jibu STOP kuacha"
                                            },
                                            {
                                                "type": "BUTTONS",
                                                "buttons": [
                                                    {
                                                        "type": "QUICK_REPLY",
                                                        "text": "Nataka"
                                                    },
                                                    {
                                                        "type": "COPY_CODE",
                                                        "example": "OFA20"
                                                    }
                                                ]
                                            }
                                        ]
                                    }
                                },
                                "draft": {
                                    "summary": "Save without submitting",
                                    "value": {
                                        "name": "karibu",
                                        "language": "en",
                                        "category": "marketing",
                                        "body": "Welcome to Amina, {{1}}!",
                                        "variable_samples": {
                                            "1": "Asha"
                                        },
                                        "submit": false
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The template as saved, with Meta's answer in `whatsapp_status` and `submission`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppTemplate",
                                            "description": "The template as saved, with Meta's answer in `whatsapp_status` and `submission`."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 418,
                                        "name": "order_shipped",
                                        "display_name": "Order shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "status": "active",
                                        "whatsapp_status": "in_review",
                                        "approved": false,
                                        "sendable": false,
                                        "rejection_reason": null,
                                        "whatsapp_business_account_id": "102290129340398",
                                        "whatsapp_template_id": "1189456212345678",
                                        "quality_rating": null,
                                        "parameter_format": "POSITIONAL",
                                        "variables": [
                                            "1",
                                            "2"
                                        ],
                                        "body": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                        "last_synced_at": "2026-09-13T09:14:02+00:00",
                                        "created_at": "2026-09-13T09:14:02+00:00",
                                        "updated_at": "2026-09-13T09:14:02+00:00",
                                        "header_type": "text",
                                        "header_text": "Oda {{1}}",
                                        "footer": "Duka la Amina",
                                        "buttons": [
                                            {
                                                "type": "url",
                                                "text": "Fuatilia",
                                                "url": "https://amina.co.tz/track/{{1}}",
                                                "example": "ORD-1042"
                                            }
                                        ],
                                        "components": [
                                            {
                                                "type": "HEADER",
                                                "format": "TEXT",
                                                "text": "Oda {{1}}",
                                                "example": {
                                                    "header_text": [
                                                        "ORD-1042"
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "BODY",
                                                "text": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                                "example": {
                                                    "body_text": [
                                                        [
                                                            "Asha",
                                                            "ORD-1042"
                                                        ]
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "FOOTER",
                                                "text": "Duka la Amina"
                                            },
                                            {
                                                "type": "BUTTONS",
                                                "buttons": [
                                                    {
                                                        "type": "URL",
                                                        "text": "Fuatilia",
                                                        "url": "https://amina.co.tz/track/{{1}}",
                                                        "example": [
                                                            "ORD-1042"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ],
                                        "deployments": [],
                                        "submission": {
                                            "submitted": true,
                                            "queued": false,
                                            "message": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Refused because of the workspace's current state; the message says what to do.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "No WhatsApp business account is connected to this workspace, so there is nothing to submit a template to. Connect one under Settings \u2192 WhatsApp first."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates/sync": {
            "post": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateSync",
                "summary": "Pull templates from WhatsApp",
                "description": "Makes this workspace a mirror of what Meta has: every APPROVED template on the account(s) that is not here yet is imported as a local row (name, language, category and full components), ones already here are refreshed from Meta's copy, and the review status of every template already submitted is re-read. Templates still in review on Meta's side that were not submitted through this platform appear once approved. Runs inside the request against Meta's paginated list, so on an account with hundreds of templates allow a few seconds. Omit `waba_id` to do every account.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "requestBody": {
                    "description": "Which account to pull from; omit for all.",
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "waba_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "One WhatsApp Business Account, or omit for every connected account. `GET /api/v3/whatsapp/accounts` lists them (`waba_id`)."
                                    }
                                }
                            },
                            "example": {
                                "waba_id": "102290129340398"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "What the pull did.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "imported": {
                                                    "type": "integer",
                                                    "description": "Approved templates that were new here and are now rows."
                                                },
                                                "updated": {
                                                    "type": "integer",
                                                    "description": "Approved templates already here whose content was refreshed from Meta."
                                                },
                                                "statuses_updated": {
                                                    "type": "integer",
                                                    "description": "Rows whose review status changed as a result."
                                                },
                                                "errors": {
                                                    "type": "array",
                                                    "description": "Per-template problems, when any \u2014 the rest of the pull still happened.",
                                                    "items": {
                                                        "type": "string",
                                                        "description": "One problem."
                                                    }
                                                }
                                            },
                                            "description": "What the pull did."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "imported": 3,
                                        "updated": 9,
                                        "statuses_updated": 1,
                                        "errors": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates/validate": {
            "post": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateValidate",
                "summary": "Check a template against WhatsApp's rules without saving it",
                "description": "Runs the checks create runs: name, language, category fit, variables and their examples, lengths, buttons and links, content WhatsApp bans (PINs, ID numbers, quick loans, betting), duplicates on the account and the account's template limit. Nothing is saved and nothing is sent to Meta. Create and update refuse with 422 when `ready` would be false; this endpoint answers 200 either way, so you can show the findings while the template is written.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "requestBody": {
                    "description": "The template, in the same shape as create.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WhatsAppTemplateWriteRequest"
                            },
                            "example": {
                                "name": "promo_as_utility",
                                "language": "en",
                                "category": "utility",
                                "body": "Hi {{1}}, get 20% off your next order this weekend only.",
                                "variable_samples": {
                                    "1": "Asha"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "What the checker found.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppTemplateCheckReport",
                                            "description": "What the checker found."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "ready": true,
                                        "counts": {
                                            "block": 0,
                                            "warn": 1,
                                            "tip": 1
                                        },
                                        "passed": 54,
                                        "issues": [
                                            {
                                                "rule": "T-CAT-02",
                                                "level": "warn",
                                                "field": "category",
                                                "message": "\u201c20% off\u201d sounds like a promotion, so WhatsApp will approve this as Marketing, which costs more and needs opt-in. Remove the offer or choose Marketing."
                                            },
                                            {
                                                "rule": "T-CAT-09",
                                                "level": "tip",
                                                "field": "category",
                                                "message": "Utility messages are free when sent within 24 hours after the customer writes to you."
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates/{template}": {
            "get": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateShow",
                "summary": "Read a template",
                "description": "One template in full: the summary fields, its content in both the flat fields and Meta's `components` shape, and its review status on every account it has been deployed to. `components` is exactly what was (or would be) submitted to Meta \u2014 post it back to create a twin, or edit and PATCH it.",
                "x-permission": "communications.templates.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 418
                        },
                        "description": "Local template id, from the list or the create response."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The template.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppTemplate",
                                            "description": "The template."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 418,
                                        "name": "order_shipped",
                                        "display_name": "Order shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "status": "active",
                                        "whatsapp_status": "in_review",
                                        "approved": false,
                                        "sendable": false,
                                        "rejection_reason": null,
                                        "whatsapp_business_account_id": "102290129340398",
                                        "whatsapp_template_id": "1189456212345678",
                                        "quality_rating": null,
                                        "parameter_format": "POSITIONAL",
                                        "variables": [
                                            "1",
                                            "2"
                                        ],
                                        "body": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                        "last_synced_at": "2026-09-13T09:14:02+00:00",
                                        "created_at": "2026-09-13T09:14:02+00:00",
                                        "updated_at": "2026-09-13T09:14:02+00:00",
                                        "header_type": "text",
                                        "header_text": "Oda {{1}}",
                                        "footer": "Duka la Amina",
                                        "buttons": [
                                            {
                                                "type": "url",
                                                "text": "Fuatilia",
                                                "url": "https://amina.co.tz/track/{{1}}",
                                                "example": "ORD-1042"
                                            }
                                        ],
                                        "components": [
                                            {
                                                "type": "HEADER",
                                                "format": "TEXT",
                                                "text": "Oda {{1}}",
                                                "example": {
                                                    "header_text": [
                                                        "ORD-1042"
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "BODY",
                                                "text": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                                "example": {
                                                    "body_text": [
                                                        [
                                                            "Asha",
                                                            "ORD-1042"
                                                        ]
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "FOOTER",
                                                "text": "Duka la Amina"
                                            },
                                            {
                                                "type": "BUTTONS",
                                                "buttons": [
                                                    {
                                                        "type": "URL",
                                                        "text": "Fuatilia",
                                                        "url": "https://amina.co.tz/track/{{1}}",
                                                        "example": [
                                                            "ORD-1042"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ],
                                        "deployments": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateUpdate",
                "summary": "Change a template",
                "description": "Any subset of the create fields. Changing content \u2014 `body`, `header_text`, `footer`, `buttons`, `components` or `category` \u2014 re-submits to Meta as an EDIT of the template it already holds (Meta then puts it back in review); changing only `display_name` or `status` does not touch Meta. `submit: false` saves a content change without re-submitting. A template in review cannot be edited on Meta's side, so the change is saved here and submitted the next time you call `\u2026/submit` once the review is over.\n\n`name`, `language` and `waba_id` cannot change: Meta knows the template by those. A template described by `components` (or imported from WhatsApp) may hold parts the flat fields cannot express, so to change part of it send the edited `components`; a flat `body` re-describes the whole content.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 418
                        },
                        "description": "Local template id, from the list or the create response."
                    }
                ],
                "requestBody": {
                    "description": "The fields to change.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WhatsAppTemplateWriteRequest"
                            },
                            "examples": {
                                "copy": {
                                    "summary": "New body copy \u2014 re-submits",
                                    "value": {
                                        "body": "Habari {{1}}, oda yako {{2}} iko njiani.",
                                        "variable_samples": {
                                            "1": "Asha",
                                            "2": "ORD-1042"
                                        }
                                    }
                                },
                                "archive": {
                                    "summary": "Hide it \u2014 no submission",
                                    "value": {
                                        "status": "archived"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The template as saved, with `submission` when a content change was submitted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppTemplate",
                                            "description": "The template as saved, with `submission` when a content change was submitted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 418,
                                        "name": "order_shipped",
                                        "display_name": "Order shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "status": "active",
                                        "whatsapp_status": "in_review",
                                        "approved": false,
                                        "sendable": false,
                                        "rejection_reason": null,
                                        "whatsapp_business_account_id": "102290129340398",
                                        "whatsapp_template_id": "1189456212345678",
                                        "quality_rating": null,
                                        "parameter_format": "POSITIONAL",
                                        "variables": [
                                            "1",
                                            "2"
                                        ],
                                        "body": "Habari {{1}}, oda yako {{2}} iko njiani.",
                                        "last_synced_at": "2026-09-13T09:14:02+00:00",
                                        "created_at": "2026-09-13T09:14:02+00:00",
                                        "updated_at": "2026-09-13T09:14:02+00:00",
                                        "header_type": "text",
                                        "header_text": "Oda {{1}}",
                                        "footer": "Duka la Amina",
                                        "buttons": [
                                            {
                                                "type": "url",
                                                "text": "Fuatilia",
                                                "url": "https://amina.co.tz/track/{{1}}",
                                                "example": "ORD-1042"
                                            }
                                        ],
                                        "components": [
                                            {
                                                "type": "HEADER",
                                                "format": "TEXT",
                                                "text": "Oda {{1}}",
                                                "example": {
                                                    "header_text": [
                                                        "ORD-1042"
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "BODY",
                                                "text": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                                "example": {
                                                    "body_text": [
                                                        [
                                                            "Asha",
                                                            "ORD-1042"
                                                        ]
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "FOOTER",
                                                "text": "Duka la Amina"
                                            },
                                            {
                                                "type": "BUTTONS",
                                                "buttons": [
                                                    {
                                                        "type": "URL",
                                                        "text": "Fuatilia",
                                                        "url": "https://amina.co.tz/track/{{1}}",
                                                        "example": [
                                                            "ORD-1042"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ],
                                        "deployments": [],
                                        "submission": {
                                            "submitted": true,
                                            "queued": false,
                                            "message": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateDelete",
                "summary": "Delete a template",
                "description": "Removes THIS language of the template from the WhatsApp Business Account (Meta keeps other languages of the same name) and archives the row here, so campaign history that pointed at it still reads. `permanent=true` deletes the row as well. A template never submitted has nothing to remove from Meta, and `removed_from_whatsapp` is false.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 418
                        },
                        "description": "Local template id, from the list or the create response."
                    },
                    {
                        "name": "permanent",
                        "in": "query",
                        "required": false,
                        "description": "Delete the local row too, not just archive it.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        },
                        "example": false
                    }
                ],
                "responses": {
                    "200": {
                        "description": "What was done.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The template id."
                                                },
                                                "archived": {
                                                    "type": "boolean",
                                                    "description": "True when the row was archived (the default)."
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True when the row was deleted (`permanent=true`)."
                                                },
                                                "removed_from_whatsapp": {
                                                    "type": "boolean",
                                                    "description": "True when Meta confirmed the removal of this language from the account."
                                                }
                                            },
                                            "description": "What was done."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 418,
                                        "archived": true,
                                        "deleted": false,
                                        "removed_from_whatsapp": true
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates/{template}/submit": {
            "post": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateSubmit",
                "summary": "Submit to Meta for review",
                "description": "Submits (or re-submits) the template to Meta now, inside the request, and answers with the template as Meta left it. Use it after fixing a `rejected` template, or for one created with `submit: false`. A template Meta already holds is edited rather than created again; one Meta is still reviewing is left alone and its current status recorded. Meta allows an approved template about ten edits a month.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 418
                        },
                        "description": "Local template id, from the list or the create response."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The template, with `submission` saying what happened.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppTemplate",
                                            "description": "The template, with `submission` saying what happened."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 418,
                                        "name": "order_shipped",
                                        "display_name": "Order shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "status": "active",
                                        "whatsapp_status": "in_review",
                                        "approved": false,
                                        "sendable": false,
                                        "rejection_reason": null,
                                        "whatsapp_business_account_id": "102290129340398",
                                        "whatsapp_template_id": "1189456212345678",
                                        "quality_rating": null,
                                        "parameter_format": "POSITIONAL",
                                        "variables": [
                                            "1",
                                            "2"
                                        ],
                                        "body": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                        "last_synced_at": "2026-09-13T09:14:02+00:00",
                                        "created_at": "2026-09-13T09:14:02+00:00",
                                        "updated_at": "2026-09-13T09:14:02+00:00",
                                        "header_type": "text",
                                        "header_text": "Oda {{1}}",
                                        "footer": "Duka la Amina",
                                        "buttons": [
                                            {
                                                "type": "url",
                                                "text": "Fuatilia",
                                                "url": "https://amina.co.tz/track/{{1}}",
                                                "example": "ORD-1042"
                                            }
                                        ],
                                        "components": [
                                            {
                                                "type": "HEADER",
                                                "format": "TEXT",
                                                "text": "Oda {{1}}",
                                                "example": {
                                                    "header_text": [
                                                        "ORD-1042"
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "BODY",
                                                "text": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                                "example": {
                                                    "body_text": [
                                                        [
                                                            "Asha",
                                                            "ORD-1042"
                                                        ]
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "FOOTER",
                                                "text": "Duka la Amina"
                                            },
                                            {
                                                "type": "BUTTONS",
                                                "buttons": [
                                                    {
                                                        "type": "URL",
                                                        "text": "Fuatilia",
                                                        "url": "https://amina.co.tz/track/{{1}}",
                                                        "example": [
                                                            "ORD-1042"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ],
                                        "deployments": [],
                                        "submission": {
                                            "submitted": true,
                                            "queued": false,
                                            "message": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates/{template}/refresh": {
            "post": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateRefresh",
                "summary": "Ask Meta for the current status",
                "description": "Reads the template from Meta right now \u2014 review status, rejection reason, quality score \u2014 and writes it on the row. The background poll and Meta's status webhook keep rows current on their own; this is for the moment you need the answer, such as right after `\u2026/submit`. By Meta id when the row has one, by name and language otherwise. `refresh.found_on_whatsapp` is false when Meta has no such template on the account, and the row is left as it was.",
                "x-permission": "communications.templates.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 418
                        },
                        "description": "Local template id, from the list or the create response."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The template as Meta reports it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppTemplate",
                                            "description": "The template as Meta reports it."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 418,
                                        "name": "order_shipped",
                                        "display_name": "Order shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "status": "active",
                                        "whatsapp_status": "approved",
                                        "approved": true,
                                        "sendable": true,
                                        "rejection_reason": null,
                                        "whatsapp_business_account_id": "102290129340398",
                                        "whatsapp_template_id": "1189456212345678",
                                        "quality_rating": "GREEN",
                                        "parameter_format": "POSITIONAL",
                                        "variables": [
                                            "1",
                                            "2"
                                        ],
                                        "body": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                        "last_synced_at": "2026-09-13T09:14:02+00:00",
                                        "created_at": "2026-09-13T09:14:02+00:00",
                                        "updated_at": "2026-09-13T09:14:02+00:00",
                                        "header_type": "text",
                                        "header_text": "Oda {{1}}",
                                        "footer": "Duka la Amina",
                                        "buttons": [
                                            {
                                                "type": "url",
                                                "text": "Fuatilia",
                                                "url": "https://amina.co.tz/track/{{1}}",
                                                "example": "ORD-1042"
                                            }
                                        ],
                                        "components": [
                                            {
                                                "type": "HEADER",
                                                "format": "TEXT",
                                                "text": "Oda {{1}}",
                                                "example": {
                                                    "header_text": [
                                                        "ORD-1042"
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "BODY",
                                                "text": "Habari {{1}}, oda yako {{2}} imetumwa leo.",
                                                "example": {
                                                    "body_text": [
                                                        [
                                                            "Asha",
                                                            "ORD-1042"
                                                        ]
                                                    ]
                                                }
                                            },
                                            {
                                                "type": "FOOTER",
                                                "text": "Duka la Amina"
                                            },
                                            {
                                                "type": "BUTTONS",
                                                "buttons": [
                                                    {
                                                        "type": "URL",
                                                        "text": "Fuatilia",
                                                        "url": "https://amina.co.tz/track/{{1}}",
                                                        "example": [
                                                            "ORD-1042"
                                                        ]
                                                    }
                                                ]
                                            }
                                        ],
                                        "deployments": [],
                                        "refresh": {
                                            "found_on_whatsapp": true,
                                            "message": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Refused because of the workspace's current state; the message says what to do.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "No WhatsApp business account is connected for this template."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "$ref": "#/components/responses/UpstreamFailure"
                    }
                }
            }
        },
        "/api/v3/whatsapp/templates/{template}/deployments": {
            "post": {
                "tags": [
                    "WhatsApp templates"
                ],
                "operationId": "v3WhatsAppTemplateDeploy",
                "summary": "Deploy to more business accounts",
                "description": "Puts an authored template on other WhatsApp Business Accounts of this workspace. Each account reviews it independently, so each gets its own deployment with its own Meta id and status \u2014 reported on the template's `deployments` and announced by `template.status_changed` with that account's id. Submission to each account is queued (202); read the template, or subscribe to the webhook, for the outcome. Deploying to an account it is already on re-submits it there.",
                "x-permission": "communications.templates.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "template",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer",
                            "example": 418
                        },
                        "description": "Local template id, from the list or the create response."
                    }
                ],
                "requestBody": {
                    "description": "The accounts to deploy to.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "waba_ids"
                                ],
                                "properties": {
                                    "waba_ids": {
                                        "type": "array",
                                        "description": "WhatsApp Business Account ids from `GET /api/v3/whatsapp/accounts`. One to twenty. `GET /api/v3/whatsapp/accounts` lists them (`waba_id`).",
                                        "items": {
                                            "type": "string",
                                            "description": "A WABA id."
                                        },
                                        "minItems": 1,
                                        "maxItems": 20
                                    }
                                }
                            },
                            "example": {
                                "waba_ids": [
                                    "102290129340777"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "The deployments, queued for submission.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "template_id": {
                                                    "type": "integer",
                                                    "description": "The template."
                                                },
                                                "deployments": {
                                                    "type": "array",
                                                    "description": "One per account, each now `pending` until its submission lands.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppTemplateDeployment"
                                                    }
                                                }
                                            },
                                            "description": "The deployments, queued for submission."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "template_id": 418,
                                        "deployments": [
                                            {
                                                "id": 91,
                                                "whatsapp_business_account_id": "102290129340777",
                                                "whatsapp_template_id": null,
                                                "whatsapp_status": "pending",
                                                "rejection_reason": null,
                                                "quality_rating": null,
                                                "category": null,
                                                "last_synced_at": null
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/accounts": {
            "get": {
                "tags": [
                    "WhatsApp"
                ],
                "operationId": "v3WhatsAppAccounts",
                "summary": "List the WhatsApp business accounts and their numbers",
                "description": "Where the identifiers come from. Every WhatsApp Business Account connected to this workspace with its phone numbers: `phone_numbers[].id` is the value `sender_id` takes on `/whatsapp/send` and the group endpoints and `from` takes on the catalogue sends and flow sessions (the number itself is accepted there too); `waba_id` is what the templates endpoints take. `default_phone_number_id` \u2014 and the `is_default` flags \u2014 say what a send without `sender_id` goes out from; null means there is no usable default and every send must name one. Readable by a key whose issuer may read the workspace's accounts or holds any permission that uses these ids. Credentials are never included.",
                "x-permission": "communications.accounts.view (or any permission that uses these ids)",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The connected accounts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "default_phone_number_id": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The phone_number_id a send without `sender_id` goes out from; null when no default is configured."
                                                },
                                                "items": {
                                                    "type": "array",
                                                    "description": "The accounts, active first.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppAccount"
                                                    }
                                                }
                                            },
                                            "description": "The connected accounts."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "default_phone_number_id": "104512345678901",
                                        "items": [
                                            {
                                                "waba_id": "102290129340398",
                                                "name": "Duka la Amina",
                                                "is_active": true,
                                                "is_default": true,
                                                "phone_numbers": [
                                                    {
                                                        "id": "104512345678901",
                                                        "phone_number": "+255700000001",
                                                        "display": "+255 700 000 001",
                                                        "is_default": true
                                                    }
                                                ],
                                                "quality_rating": "GREEN",
                                                "messaging_tier": "TIER_1K",
                                                "templates_count": 12,
                                                "catalogues_count": 1,
                                                "last_synced_at": "2026-09-13T09:14:02+00:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/sms/senders": {
            "get": {
                "tags": [
                    "SMS"
                ],
                "operationId": "v3SmsSenders",
                "summary": "List the identities an SMS can be sent as",
                "description": "Where `sender_id` comes from. Every identity this workspace may send SMS as \u2014 approved alphanumeric sender IDs, its own SMS-capable phone numbers, and its active short codes \u2014 with `value` being exactly what `sender_id` takes on `/sms/send` and `/sms/campaign`. Only usable identities are listed (a sender ID still under review is not). Readable by a key whose issuer may read the workspace's accounts or holds any permission that uses these ids.",
                "x-permission": "communications.accounts.view (or any permission that uses these ids)",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The sending identities.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "The identities, sender IDs first, then numbers, then short codes.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/SmsSender"
                                                    }
                                                }
                                            },
                                            "description": "The sending identities."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "type": "sender_id",
                                                "value": "AMINA",
                                                "label": "AMINA",
                                                "status": "approved"
                                            },
                                            {
                                                "type": "phone_number",
                                                "value": "+255700000001",
                                                "label": "Main line",
                                                "status": "active"
                                            },
                                            {
                                                "type": "short_code",
                                                "value": "15551",
                                                "label": "Promotions",
                                                "status": "active"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contact-groups": {
            "get": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupList",
                "summary": "List contact groups",
                "description": "Where `{group_id}` comes from. Every contact path takes a group, and until now an integrator had to read its id off the dashboard \u2014 this is the list, with how many people each group holds, how many still accept messages, and the extra fields its contacts may carry. Either the numeric `id` or the `uid` works anywhere a group is named.",
                "x-permission": "contacts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Narrow to groups in this state; `all` includes retired ones (the default returns every group).",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "active",
                                "inactive",
                                "all"
                            ]
                        },
                        "example": "active"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Free text over the group name.",
                        "schema": {
                            "type": "string",
                            "maxLength": 120
                        },
                        "example": "Dar"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The groups, most recently changed first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "The groups, most recently changed first.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/ContactGroup"
                                                    }
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "The groups, most recently changed first."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 42,
                                                "uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                                "name": "Wateja wa Dar",
                                                "status": "active",
                                                "contacts_count": 1180,
                                                "subscribed_count": 1094,
                                                "custom_fields": [
                                                    {
                                                        "key": "order_ref",
                                                        "label": "Order reference",
                                                        "type": "text"
                                                    },
                                                    {
                                                        "key": "branch",
                                                        "label": "Branch",
                                                        "type": "select"
                                                    }
                                                ],
                                                "created_at": "2026-09-14T09:14:02+00:00",
                                                "updated_at": "2026-09-14T09:14:02+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupCreate",
                "summary": "Create a contact group",
                "description": "Creates a group to put contacts in. `custom_fields` declares the extra fields its contacts may carry \u2014 a contact can still be given an undeclared key, but a declared one is what the dashboard shows a column for and what a campaign addresses as `{{cf:key}}`. Duplicate keys are refused.",
                "x-permission": "contacts.create",
                "x-permission-scope": "controller",
                "requestBody": {
                    "description": "The group.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ContactGroupWriteRequest"
                            },
                            "example": {
                                "name": "Wateja wa Dar",
                                "custom_fields": [
                                    {
                                        "key": "order_ref",
                                        "label": "Order reference",
                                        "type": "text"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The group as created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/ContactGroup",
                                            "description": "The group as created."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 42,
                                        "uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "name": "Wateja wa Dar",
                                        "status": "active",
                                        "contacts_count": 1180,
                                        "subscribed_count": 1094,
                                        "custom_fields": [
                                            {
                                                "key": "order_ref",
                                                "label": "Order reference",
                                                "type": "text"
                                            },
                                            {
                                                "key": "branch",
                                                "label": "Branch",
                                                "type": "select"
                                            }
                                        ],
                                        "created_at": "2026-09-14T09:14:02+00:00",
                                        "updated_at": "2026-09-14T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contact-groups/{group}": {
            "get": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupShow",
                "summary": "Read a contact group",
                "description": "One group with its counts and the extra fields it declares \u2014 what a caller needs before writing a contact into it.",
                "x-permission": "contacts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The group.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/ContactGroup",
                                            "description": "The group."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 42,
                                        "uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "name": "Wateja wa Dar",
                                        "status": "active",
                                        "contacts_count": 1180,
                                        "subscribed_count": 1094,
                                        "custom_fields": [
                                            {
                                                "key": "order_ref",
                                                "label": "Order reference",
                                                "type": "text"
                                            },
                                            {
                                                "key": "branch",
                                                "label": "Branch",
                                                "type": "select"
                                            }
                                        ],
                                        "created_at": "2026-09-14T09:14:02+00:00",
                                        "updated_at": "2026-09-14T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupUpdate",
                "summary": "Change a contact group",
                "description": "Rename a group, retire it with `status: inactive`, or change the fields it declares. `custom_fields` replaces the declaration rather than merging into it; the values already stored on contacts are untouched either way.",
                "x-permission": "contacts.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    }
                ],
                "requestBody": {
                    "description": "The fields to change.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ContactGroupWriteRequest"
                            },
                            "example": {
                                "name": "Wateja wa Mwanza"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The group as saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/ContactGroup",
                                            "description": "The group as saved."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 42,
                                        "uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "name": "Wateja wa Dar",
                                        "status": "active",
                                        "contacts_count": 1180,
                                        "subscribed_count": 1094,
                                        "custom_fields": [
                                            {
                                                "key": "order_ref",
                                                "label": "Order reference",
                                                "type": "text"
                                            },
                                            {
                                                "key": "branch",
                                                "label": "Branch",
                                                "type": "select"
                                            }
                                        ],
                                        "created_at": "2026-09-14T09:14:02+00:00",
                                        "updated_at": "2026-09-14T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "409": {
                        "description": "Refused: Uncategorised keeps its name and stays active, and a website's chat group stays active.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Uncategorised keeps its name and stays active. Only its fields can change."
                                }
                            }
                        }
                    }
                }
            },
            "delete": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupDelete",
                "summary": "Delete a contact group",
                "description": "Deleting a group deletes every contact in it. A group that still holds people is refused with 409 and the count, unless you repeat the call with `force=true` \u2014 there is no undo, and the contacts do not move anywhere.",
                "x-permission": "contacts.delete",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    },
                    {
                        "name": "force",
                        "in": "query",
                        "required": false,
                        "description": "Delete the group even though it still holds contacts, taking them with it.",
                        "schema": {
                            "type": "boolean",
                            "default": false
                        },
                        "example": true
                    }
                ],
                "responses": {
                    "200": {
                        "description": "What was deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The group that was deleted."
                                                },
                                                "uid": {
                                                    "type": "string",
                                                    "description": "Its UUID."
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true on a 200 here."
                                                },
                                                "contacts_deleted": {
                                                    "type": "integer",
                                                    "description": "How many contacts went with it."
                                                }
                                            },
                                            "description": "What was deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 42,
                                        "uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "deleted": true,
                                        "contacts_deleted": 1180
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Refused because of the state the data is in; the message says what to do. The group still holds people (repeat with `force=true`), or it is a group the system keeps (Uncategorised, or a website's chat group), which no `force` deletes.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This group still holds 1180 contact(s), and deleting it deletes them too. Move them first, or repeat with ?force=true."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contact-groups/{group}/contacts": {
            "get": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupContactList",
                "summary": "List the contacts in a group",
                "description": "The people in one group, most recently changed first. `search` matches the name, the national number, and the full number with punctuation stripped, so a number pasted as `+255 712 345 678` finds them.",
                "x-permission": "contacts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Free text over name and number.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Asha"
                    },
                    {
                        "name": "subscribed",
                        "in": "query",
                        "required": false,
                        "description": "Only those who do (or do not) still accept messages.",
                        "schema": {
                            "type": "boolean"
                        },
                        "example": true
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The contacts in this group.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "The contacts in this group.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Contact"
                                                    }
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "The contacts in this group."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 9201,
                                                "uid": "ctc_7f2ab1c93de04a6b8f10",
                                                "group_id": 42,
                                                "group_uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                                "name": "Asha Mwinyi",
                                                "country_code": "255",
                                                "phone_number": "712345678",
                                                "full_phone_number": "255712345678",
                                                "is_subscribed": true,
                                                "custom_field_values": {
                                                    "order_ref": "ORD-1042",
                                                    "branch": "Mlimani"
                                                },
                                                "created_at": "2026-09-14T09:14:02+00:00",
                                                "updated_at": "2026-09-14T09:14:02+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupContactCreate",
                "summary": "Add a contact to a group",
                "description": "Creates one contact. The REST twin of `POST /api/v3/contacts/{group_id}/store`, which still works and does the same thing.",
                "x-permission": "contacts.create",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    }
                ],
                "requestBody": {
                    "description": "The contact.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ContactWriteRequest"
                            },
                            "example": {
                                "PHONE": "0712345678",
                                "country_code": "255",
                                "name": "Asha Mwinyi",
                                "order_ref": "ORD-1042"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The contact as created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Contact",
                                            "description": "The contact as created."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9201,
                                        "uid": "ctc_7f2ab1c93de04a6b8f10",
                                        "group_id": 42,
                                        "group_uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "name": "Asha Mwinyi",
                                        "country_code": "255",
                                        "phone_number": "712345678",
                                        "full_phone_number": "255712345678",
                                        "is_subscribed": true,
                                        "custom_field_values": {
                                            "order_ref": "ORD-1042",
                                            "branch": "Mlimani"
                                        },
                                        "created_at": "2026-09-14T09:14:02+00:00",
                                        "updated_at": "2026-09-14T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contact-groups/{group}/contacts/batch": {
            "post": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupContactBatch",
                "summary": "Import many contacts at once",
                "description": "Up to 500 contacts in one call \u2014 the import an integration actually has, instead of one POST per person. A number already in the group is UPDATED (its custom fields merge, exactly as PATCH does, and a row with no `name` does not rename anybody); a new one is created. `skip_existing` leaves the ones already there completely untouched.\n\nEvery row is judged on its own: a row that fails validation is reported in `problems` with its index and the rest still apply, and the answer is 207 when any row was rejected, 200 when none was. `results` names the outcome of every row that landed, so a caller knows what it changed without diffing anything.",
                "x-permission": "contacts.import",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    }
                ],
                "requestBody": {
                    "description": "The contacts to import.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "contacts"
                                ],
                                "properties": {
                                    "contacts": {
                                        "type": "array",
                                        "description": "The rows, 1 to 500 of them, each shaped like a single create.",
                                        "items": {
                                            "$ref": "#/components/schemas/ContactWriteRequest"
                                        },
                                        "minItems": 1,
                                        "maxItems": 500
                                    },
                                    "skip_existing": {
                                        "type": "boolean",
                                        "description": "Leave a number that is already in the group exactly as it is, rather than updating it. Defaults false."
                                    }
                                }
                            },
                            "example": {
                                "contacts": [
                                    {
                                        "PHONE": "0712345678",
                                        "country_code": "255",
                                        "name": "Asha Mwinyi",
                                        "order_ref": "ORD-1042"
                                    },
                                    {
                                        "PHONE": "0754000111",
                                        "country_code": "255",
                                        "name": "Juma Ally"
                                    }
                                ],
                                "skip_existing": false
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Every row applied.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "group_id": {
                                                    "type": "integer",
                                                    "description": "The group they went into."
                                                },
                                                "received": {
                                                    "type": "integer",
                                                    "description": "How many rows you sent."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "How many were new."
                                                },
                                                "updated": {
                                                    "type": "integer",
                                                    "description": "How many matched a number already in the group."
                                                },
                                                "skipped": {
                                                    "type": "integer",
                                                    "description": "How many were left alone because of `skip_existing`."
                                                },
                                                "rejected": {
                                                    "type": "integer",
                                                    "description": "How many failed validation and did nothing."
                                                },
                                                "results": {
                                                    "type": "array",
                                                    "description": "One entry per row that landed.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/ContactBatchResult"
                                                    }
                                                },
                                                "problems": {
                                                    "type": "array",
                                                    "description": "One entry per rejected row.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "A rejected row.",
                                                        "properties": {
                                                            "index": {
                                                                "type": "integer",
                                                                "description": "Its position in the array you sent."
                                                            },
                                                            "errors": {
                                                                "type": "object",
                                                                "description": "Field-by-field validation messages.",
                                                                "additionalProperties": {
                                                                    "type": "array",
                                                                    "description": "The messages for that field.",
                                                                    "items": {
                                                                        "type": "string",
                                                                        "description": "One message."
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "description": "Every row applied."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "group_id": 42,
                                        "received": 2,
                                        "created": 1,
                                        "updated": 1,
                                        "skipped": 0,
                                        "rejected": 0,
                                        "results": [
                                            {
                                                "index": 0,
                                                "uid": "ctc_7f2ab1c93de04a6b8f10",
                                                "outcome": "updated"
                                            },
                                            {
                                                "index": 1,
                                                "uid": "ctc_88c1de40ab7392f5c001",
                                                "outcome": "created"
                                            }
                                        ],
                                        "problems": []
                                    }
                                }
                            }
                        }
                    },
                    "207": {
                        "description": "Some rows were rejected; the rest applied.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "received": {
                                                    "type": "integer",
                                                    "description": "How many rows you sent."
                                                },
                                                "created": {
                                                    "type": "integer",
                                                    "description": "How many were new."
                                                },
                                                "updated": {
                                                    "type": "integer",
                                                    "description": "How many matched an existing number."
                                                },
                                                "skipped": {
                                                    "type": "integer",
                                                    "description": "How many `skip_existing` left alone."
                                                },
                                                "rejected": {
                                                    "type": "integer",
                                                    "description": "How many failed validation."
                                                },
                                                "results": {
                                                    "type": "array",
                                                    "description": "The rows that landed.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/ContactBatchResult"
                                                    }
                                                },
                                                "problems": {
                                                    "type": "array",
                                                    "description": "The rows that did not, with why.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "A rejected row.",
                                                        "additionalProperties": true,
                                                        "properties": {
                                                            "index": {
                                                                "type": "integer",
                                                                "description": "Its position in the array you sent."
                                                            },
                                                            "errors": {
                                                                "type": "object",
                                                                "description": "Field-by-field validation messages.",
                                                                "additionalProperties": true
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "description": "Some rows were rejected; the rest applied."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "received": 3,
                                        "created": 1,
                                        "updated": 1,
                                        "skipped": 0,
                                        "rejected": 1,
                                        "results": [
                                            {
                                                "index": 0,
                                                "uid": "ctc_7f2ab1c93de04a6b8f10",
                                                "outcome": "updated"
                                            }
                                        ],
                                        "problems": [
                                            {
                                                "index": 2,
                                                "errors": {
                                                    "PHONE": [
                                                        "The PHONE field is required."
                                                    ]
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contact-groups/{group}/contacts/{contact}": {
            "get": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupContactShow",
                "summary": "Read a contact",
                "description": "One contact. The REST twin of `POST /api/v3/contacts/{group_id}/search/{uid}`.",
                "x-permission": "contacts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    },
                    {
                        "name": "contact",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": "ctc_7f2ab1c93de04a6b8f10"
                        },
                        "description": "The contact, by its UID or numeric id."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The contact.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Contact",
                                            "description": "The contact."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9201,
                                        "uid": "ctc_7f2ab1c93de04a6b8f10",
                                        "group_id": 42,
                                        "group_uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "name": "Asha Mwinyi",
                                        "country_code": "255",
                                        "phone_number": "712345678",
                                        "full_phone_number": "255712345678",
                                        "is_subscribed": true,
                                        "custom_field_values": {
                                            "order_ref": "ORD-1042",
                                            "branch": "Mlimani"
                                        },
                                        "created_at": "2026-09-14T09:14:02+00:00",
                                        "updated_at": "2026-09-14T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupContactUpdate",
                "summary": "Change a contact",
                "description": "Changes exactly what you send and nothing else. Custom fields MERGE into what is stored \u2014 send a key as `null` to remove it \u2014 and the name, the number and the subscription each keep their current value when the payload is silent about them. `PHONE` is not required unless the number itself is changing.\n\nThis is a change of behaviour: until 2026-09-14 this endpoint replaced the whole custom-field map and renamed the contact after their phone number whenever `name` was absent, so a call meant to flip `is_subscribed` quietly destroyed data. A caller that followed the old advice \u2014 read, merge, send everything \u2014 gets the same result as before.",
                "x-permission": "contacts.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    },
                    {
                        "name": "contact",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": "ctc_7f2ab1c93de04a6b8f10"
                        },
                        "description": "The contact, by its UID or numeric id."
                    }
                ],
                "requestBody": {
                    "description": "The fields to change.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/ContactWriteRequest"
                            },
                            "example": {
                                "name": "Asha Juma",
                                "order_ref": "ORD-2099"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The contact as saved.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Contact",
                                            "description": "The contact as saved."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9201,
                                        "uid": "ctc_7f2ab1c93de04a6b8f10",
                                        "group_id": 42,
                                        "group_uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                        "name": "Asha Mwinyi",
                                        "country_code": "255",
                                        "phone_number": "712345678",
                                        "full_phone_number": "255712345678",
                                        "is_subscribed": true,
                                        "custom_field_values": {
                                            "order_ref": "ORD-1042",
                                            "branch": "Mlimani"
                                        },
                                        "created_at": "2026-09-14T09:14:02+00:00",
                                        "updated_at": "2026-09-14T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactGroupContactDelete",
                "summary": "Delete a contact",
                "description": "Removes the contact from the group permanently. The REST twin of `DELETE /api/v3/contacts/{group_id}/delete/{uid}`.",
                "x-permission": "contacts.delete",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "group",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": 42
                        },
                        "description": "The group, by numeric id or UUID."
                    },
                    {
                        "name": "contact",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "string",
                            "example": "ctc_7f2ab1c93de04a6b8f10"
                        },
                        "description": "The contact, by its UID or numeric id."
                    }
                ],
                "responses": {
                    "200": {
                        "description": "What was deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true on a 200 here."
                                                },
                                                "uid": {
                                                    "type": "string",
                                                    "description": "The contact that was deleted."
                                                }
                                            },
                                            "description": "What was deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "deleted": true,
                                        "uid": "ctc_7f2ab1c93de04a6b8f10"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/contacts": {
            "get": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactSearch",
                "summary": "Find a contact across every group",
                "description": "Every contact in the workspace, whichever group holds them \u2014 the answer to \"who is this number?\" when the caller does not know. `q` matches the name, the national number and the full number with punctuation stripped. `group_id` narrows it back to one group.",
                "x-permission": "contacts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Free text over name and number. `search` is an alias.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "712345678"
                    },
                    {
                        "name": "group_id",
                        "in": "query",
                        "required": false,
                        "description": "Only this group, by numeric id or UUID.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "42"
                    },
                    {
                        "name": "subscribed",
                        "in": "query",
                        "required": false,
                        "description": "Only those who do (or do not) still accept messages.",
                        "schema": {
                            "type": "boolean"
                        },
                        "example": true
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The matching contacts, most recently changed first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "The matching contacts, most recently changed first.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Contact"
                                                    }
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "The matching contacts, most recently changed first."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 9201,
                                                "uid": "ctc_7f2ab1c93de04a6b8f10",
                                                "group_id": 42,
                                                "group_uid": "9f3a1c20-5d6e-4a71-9c3b-2f1a0e7b8c44",
                                                "name": "Asha Mwinyi",
                                                "country_code": "255",
                                                "phone_number": "712345678",
                                                "full_phone_number": "255712345678",
                                                "is_subscribed": true,
                                                "custom_field_values": {
                                                    "order_ref": "ORD-1042",
                                                    "branch": "Mlimani"
                                                },
                                                "created_at": "2026-09-14T09:14:02+00:00",
                                                "updated_at": "2026-09-14T09:14:02+00:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts": {
            "get": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostList",
                "summary": "List posts",
                "description": "Posts in this workspace: scheduled ones first (soonest first), then newest. `status=sent` is published or partially published; `failed` includes posts with a target waiting on a reconnect.",
                "x-permission": "posts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Only posts in this state.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "scheduled",
                                "publishing",
                                "published",
                                "partially_published",
                                "failed",
                                "cancelled",
                                "sent"
                            ]
                        },
                        "example": "scheduled"
                    },
                    {
                        "name": "platform",
                        "in": "query",
                        "required": false,
                        "description": "Only posts with a target on this platform.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "facebook",
                                "instagram",
                                "tiktok",
                                "youtube",
                                "linkedin"
                            ]
                        },
                        "example": "facebook"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Free text over the post body.",
                        "schema": {
                            "type": "string",
                            "maxLength": 120
                        },
                        "example": "chapati"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of posts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/PostPage",
                                            "description": "A page of posts."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "uid": "pub_9k2f3m1x",
                                                "status": "scheduled",
                                                "schedule_status": "pending",
                                                "scheduled_at": "2026-09-20T09:00:00+03:00",
                                                "scheduled_tz": "Africa/Dar_es_Salaam",
                                                "published_at": null,
                                                "created_at": "2026-09-18T10:12:00+03:00",
                                                "body_excerpt": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "thumbnail": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                "media_count": 1,
                                                "media_kind": "image",
                                                "platforms": [
                                                    "facebook"
                                                ],
                                                "targets_summary": {
                                                    "pending": 1
                                                },
                                                "targets": [
                                                    {
                                                        "id": 31,
                                                        "platform": "facebook",
                                                        "status": "pending"
                                                    }
                                                ],
                                                "comments_href": null,
                                                "metrics": null,
                                                "comment_count": 0,
                                                "unanswered_count": 0,
                                                "created_by": {
                                                    "id": 12,
                                                    "name": "Amina Juma"
                                                }
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 20,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostCreate",
                "summary": "Create a post",
                "description": "Creates a post through the same rules as the composer. `schedule.mode` decides what happens next: `draft` (default) saves it; `now` publishes at once; `later` schedules it at `at`. Every target must be a connected account (`GET /api/v3/posts/accounts`) and, for now/later, able to publish. Per-platform `options` are validated against that platform (YouTube needs `title` and `made_for_kids`, TikTok `privacy_level`); pre-flight warnings block now/later until listed in `accept_warnings`. The same `idempotency_key` again returns the existing post with 200.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "requestBody": {
                    "description": "The post.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PostWriteRequest",
                                "description": "The post to write."
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example",
                                    "value": {
                                        "targets": [
                                            4,
                                            7
                                        ],
                                        "content": {
                                            "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                            "media": [
                                                {
                                                    "asset": "ast_7h3k2p",
                                                    "alt_text": "Chapati on a plate"
                                                }
                                            ],
                                            "first_comment": "#chapati #dar"
                                        },
                                        "options": {
                                            "tiktok": {
                                                "privacy_level": "PUBLIC_TO_EVERYONE"
                                            }
                                        },
                                        "schedule": {
                                            "mode": "later",
                                            "at": "2026-09-20T09:00:00",
                                            "tz": "Africa/Dar_es_Salaam"
                                        },
                                        "idempotency_key": "order-42"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The post was created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "post"
                                            ],
                                            "properties": {
                                                "post": {
                                                    "$ref": "#/components/schemas/Post",
                                                    "description": "The post in full."
                                                },
                                                "notice": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Anything the scheduler wants you to know."
                                                },
                                                "existing": {
                                                    "type": "boolean",
                                                    "description": "False on a fresh create."
                                                }
                                            },
                                            "description": "The post was created."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "post": {
                                            "uid": "pub_9k2f3m1x",
                                            "status": "scheduled",
                                            "schedule_status": "pending",
                                            "scheduled_at": "2026-09-20T09:00:00+03:00",
                                            "scheduled_tz": "Africa/Dar_es_Salaam",
                                            "published_at": null,
                                            "completed_at": null,
                                            "created_at": "2026-09-18T10:12:00+03:00",
                                            "updated_at": "2026-09-18T10:15:00+03:00",
                                            "created_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_at": "2026-09-18T10:15:00+03:00",
                                            "content": {
                                                "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "media": [
                                                    {
                                                        "asset": "ast_7h3k2p",
                                                        "alt_text": "Chapati on a plate"
                                                    }
                                                ],
                                                "first_comment": "#chapati #dar"
                                            },
                                            "overrides": [],
                                            "options": {
                                                "tiktok": {
                                                    "privacy_level": "PUBLIC_TO_EVERYONE"
                                                }
                                            },
                                            "options_overrides": [],
                                            "targets": [
                                                {
                                                    "id": 31,
                                                    "social_account_id": 4,
                                                    "platform": "facebook",
                                                    "status": "pending",
                                                    "provider_post_id": null,
                                                    "permalink": null,
                                                    "error_message": null,
                                                    "published_at": null
                                                }
                                            ],
                                            "media": [
                                                {
                                                    "uid": "ast_7h3k2p",
                                                    "kind": "image",
                                                    "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                    "status": "ready"
                                                }
                                            ],
                                            "verification": {
                                                "errors": [],
                                                "warnings": []
                                            },
                                            "notes": null,
                                            "idempotency_key": "order-42",
                                            "approval": null
                                        },
                                        "notice": null,
                                        "existing": false
                                    }
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "The idempotency key matched an existing post; it is returned unchanged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "post"
                                            ],
                                            "properties": {
                                                "post": {
                                                    "$ref": "#/components/schemas/Post",
                                                    "description": "The post in full."
                                                },
                                                "notice": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Always null here."
                                                },
                                                "existing": {
                                                    "type": "boolean",
                                                    "description": "True."
                                                }
                                            },
                                            "description": "The idempotency key matched an existing post; it is returned unchanged."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "post": {
                                            "uid": "pub_9k2f3m1x",
                                            "status": "scheduled",
                                            "schedule_status": "pending",
                                            "scheduled_at": "2026-09-20T09:00:00+03:00",
                                            "scheduled_tz": "Africa/Dar_es_Salaam",
                                            "published_at": null,
                                            "completed_at": null,
                                            "created_at": "2026-09-18T10:12:00+03:00",
                                            "updated_at": "2026-09-18T10:15:00+03:00",
                                            "created_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_at": "2026-09-18T10:15:00+03:00",
                                            "content": {
                                                "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "media": [
                                                    {
                                                        "asset": "ast_7h3k2p",
                                                        "alt_text": "Chapati on a plate"
                                                    }
                                                ],
                                                "first_comment": "#chapati #dar"
                                            },
                                            "overrides": [],
                                            "options": {
                                                "tiktok": {
                                                    "privacy_level": "PUBLIC_TO_EVERYONE"
                                                }
                                            },
                                            "options_overrides": [],
                                            "targets": [
                                                {
                                                    "id": 31,
                                                    "social_account_id": 4,
                                                    "platform": "facebook",
                                                    "status": "pending",
                                                    "provider_post_id": null,
                                                    "permalink": null,
                                                    "error_message": null,
                                                    "published_at": null
                                                }
                                            ],
                                            "media": [
                                                {
                                                    "uid": "ast_7h3k2p",
                                                    "kind": "image",
                                                    "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                    "status": "ready"
                                                }
                                            ],
                                            "verification": {
                                                "errors": [],
                                                "warnings": []
                                            },
                                            "notes": null,
                                            "idempotency_key": "order-42",
                                            "approval": null
                                        },
                                        "notice": null,
                                        "existing": true
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The pre-flight found errors, or a warning was not accepted. `verification` lists them by target.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope",
                                    "description": "See the referenced schema."
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This post has warnings to accept before it can be scheduled.",
                                    "verification": {
                                        "warnings": [
                                            {
                                                "code": "caption_truncated",
                                                "target": 4
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/accounts": {
            "get": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostAccountList",
                "summary": "List publish targets",
                "description": "The connected accounts a post can go to, with each one's publishing state and why it cannot publish when it cannot. Bounded by what the key's owner is assigned to.",
                "x-permission": "posts.view",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The accounts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "Every account this key may post to.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/PostAccount",
                                                        "description": "A publish target."
                                                    }
                                                }
                                            },
                                            "description": "The accounts."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 4,
                                                "platform": "facebook",
                                                "name": "Duka la Amina",
                                                "handle": null,
                                                "avatar": null,
                                                "publish_enabled": true,
                                                "needs_reconnect": false,
                                                "needs_reconnect_reason": null,
                                                "reason_text": null,
                                                "publish_tier": "ready",
                                                "publish_state": "on",
                                                "publish_gate": null,
                                                "publish_defaults": [],
                                                "insights_status": "ok",
                                                "author_kind": null,
                                                "token_expires_at": null,
                                                "health": {
                                                    "checked_at": "2026-09-18T04:05:00+03:00",
                                                    "quota": null
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/media": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostMediaCreate",
                "summary": "Upload media for a post",
                "description": "Send a multipart `file` (JPEG, PNG, WebP, HEIC, GIF, MP4, MOV, WebM) or an https `url` to fetch. The asset comes back `processing`; poll `GET /api/v3/posts/media/{uid}` until it is `ready`, then put its uid in `content.media`. Pictures over 1920px on the long side are resized; videos are probed for duration, aspect and audio.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "requestBody": {
                    "description": "A file or a URL.",
                    "required": true,
                    "content": {
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "description": "The file.",
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "format": "binary",
                                        "description": "The picture or video."
                                    }
                                }
                            },
                            "examples": {
                                "file": {
                                    "summary": "A file",
                                    "value": {
                                        "file": "(binary)"
                                    }
                                }
                            }
                        },
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "A URL to fetch.",
                                "required": [
                                    "url"
                                ],
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "description": "An https URL of a picture or video to fetch."
                                    }
                                }
                            },
                            "examples": {
                                "url": {
                                    "summary": "From a URL",
                                    "value": {
                                        "url": "https://cdn.example.co.tz/chapati.jpg"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The asset, processing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "media"
                                            ],
                                            "properties": {
                                                "media": {
                                                    "$ref": "#/components/schemas/PostMediaAsset",
                                                    "description": "An uploaded media asset."
                                                }
                                            },
                                            "description": "The asset, processing."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "media": {
                                            "uid": "ast_7h3k2p",
                                            "kind": "image",
                                            "mime_type": "image/jpeg",
                                            "original_name": "chapati.jpg",
                                            "size": 412000,
                                            "status": "processing",
                                            "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                            "thumbnail_url": null,
                                            "probe": null,
                                            "warnings": []
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/media/{uid}": {
            "get": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostMediaShow",
                "summary": "Read a media asset",
                "description": "One uploaded asset and its state; `ready` means it can go on a post.",
                "x-permission": "posts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The asset uid (ast_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "ast_7h3k2p"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The asset.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "media"
                                            ],
                                            "properties": {
                                                "media": {
                                                    "$ref": "#/components/schemas/PostMediaAsset",
                                                    "description": "An uploaded media asset."
                                                }
                                            },
                                            "description": "The asset."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "media": {
                                            "uid": "ast_7h3k2p",
                                            "kind": "image",
                                            "mime_type": "image/jpeg",
                                            "original_name": "chapati.jpg",
                                            "size": 412000,
                                            "status": "ready",
                                            "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                            "thumbnail_url": null,
                                            "probe": {
                                                "width": 1080,
                                                "height": 1350,
                                                "duration_ms": null,
                                                "aspect": 0.8,
                                                "has_audio": null
                                            },
                                            "warnings": []
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/{uid}": {
            "get": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostShow",
                "summary": "Read a post",
                "description": "One post in full: content, per-platform options, every target's state and public link, the pre-flight report, and any pending approval.",
                "x-permission": "posts.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The post id (pub_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pub_9k2f3m1x"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The post.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Post",
                                            "description": "The post."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "uid": "pub_9k2f3m1x",
                                        "status": "scheduled",
                                        "schedule_status": "pending",
                                        "scheduled_at": "2026-09-20T09:00:00+03:00",
                                        "scheduled_tz": "Africa/Dar_es_Salaam",
                                        "published_at": null,
                                        "completed_at": null,
                                        "created_at": "2026-09-18T10:12:00+03:00",
                                        "updated_at": "2026-09-18T10:15:00+03:00",
                                        "created_by": {
                                            "id": 12,
                                            "name": "Amina Juma"
                                        },
                                        "approved_by": {
                                            "id": 12,
                                            "name": "Amina Juma"
                                        },
                                        "approved_at": "2026-09-18T10:15:00+03:00",
                                        "content": {
                                            "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                            "media": [
                                                {
                                                    "asset": "ast_7h3k2p",
                                                    "alt_text": "Chapati on a plate"
                                                }
                                            ],
                                            "first_comment": "#chapati #dar"
                                        },
                                        "overrides": [],
                                        "options": {
                                            "tiktok": {
                                                "privacy_level": "PUBLIC_TO_EVERYONE"
                                            }
                                        },
                                        "options_overrides": [],
                                        "targets": [
                                            {
                                                "id": 31,
                                                "social_account_id": 4,
                                                "platform": "facebook",
                                                "status": "pending",
                                                "provider_post_id": null,
                                                "permalink": null,
                                                "error_message": null,
                                                "published_at": null
                                            }
                                        ],
                                        "media": [
                                            {
                                                "uid": "ast_7h3k2p",
                                                "kind": "image",
                                                "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                "status": "ready"
                                            }
                                        ],
                                        "verification": {
                                            "errors": [],
                                            "warnings": []
                                        },
                                        "notes": null,
                                        "idempotency_key": "order-42",
                                        "approval": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostUpdate",
                "summary": "Replace a post's content",
                "description": "Replaces the content, targets and options of a draft or a pending scheduled post \u2014 the same body as create. A post already publishing answers 409. Editing an approved post withdraws the approval; `schedule.mode` re-records it.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The post id (pub_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pub_9k2f3m1x"
                    }
                ],
                "requestBody": {
                    "description": "The post.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PostWriteRequest",
                                "description": "The post to write."
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example",
                                    "value": {
                                        "targets": [
                                            4,
                                            7
                                        ],
                                        "content": {
                                            "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                            "media": [
                                                {
                                                    "asset": "ast_7h3k2p",
                                                    "alt_text": "Chapati on a plate"
                                                }
                                            ],
                                            "first_comment": "#chapati #dar"
                                        },
                                        "options": {
                                            "tiktok": {
                                                "privacy_level": "PUBLIC_TO_EVERYONE"
                                            }
                                        },
                                        "schedule": {
                                            "mode": "later",
                                            "at": "2026-09-20T09:00:00",
                                            "tz": "Africa/Dar_es_Salaam"
                                        },
                                        "idempotency_key": "order-42"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The updated post.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "post"
                                            ],
                                            "properties": {
                                                "post": {
                                                    "$ref": "#/components/schemas/Post",
                                                    "description": "The post in full."
                                                },
                                                "notice": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Anything the scheduler wants you to know."
                                                }
                                            },
                                            "description": "The updated post."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "post": {
                                            "uid": "pub_9k2f3m1x",
                                            "status": "scheduled",
                                            "schedule_status": "pending",
                                            "scheduled_at": "2026-09-20T09:00:00+03:00",
                                            "scheduled_tz": "Africa/Dar_es_Salaam",
                                            "published_at": null,
                                            "completed_at": null,
                                            "created_at": "2026-09-18T10:12:00+03:00",
                                            "updated_at": "2026-09-18T10:15:00+03:00",
                                            "created_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_at": "2026-09-18T10:15:00+03:00",
                                            "content": {
                                                "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "media": [
                                                    {
                                                        "asset": "ast_7h3k2p",
                                                        "alt_text": "Chapati on a plate"
                                                    }
                                                ],
                                                "first_comment": "#chapati #dar"
                                            },
                                            "overrides": [],
                                            "options": {
                                                "tiktok": {
                                                    "privacy_level": "PUBLIC_TO_EVERYONE"
                                                }
                                            },
                                            "options_overrides": [],
                                            "targets": [
                                                {
                                                    "id": 31,
                                                    "social_account_id": 4,
                                                    "platform": "facebook",
                                                    "status": "pending",
                                                    "provider_post_id": null,
                                                    "permalink": null,
                                                    "error_message": null,
                                                    "published_at": null
                                                }
                                            ],
                                            "media": [
                                                {
                                                    "uid": "ast_7h3k2p",
                                                    "kind": "image",
                                                    "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                    "status": "ready"
                                                }
                                            ],
                                            "verification": {
                                                "errors": [],
                                                "warnings": []
                                            },
                                            "notes": null,
                                            "idempotency_key": "order-42",
                                            "approval": null
                                        },
                                        "notice": null
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The post is already publishing, or the pre-flight blocked the requested schedule.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope",
                                    "description": "See the referenced schema."
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This post is already publishing and can no longer be edited."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostDelete",
                "summary": "Delete a post",
                "description": "Removes the post here. Anything already published on a platform stays there; a post that is publishing right now answers 409.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The post id (pub_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pub_9k2f3m1x"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "deleted",
                                                "uid"
                                            ],
                                            "properties": {
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "True."
                                                },
                                                "uid": {
                                                    "type": "string",
                                                    "description": "The uid that was deleted."
                                                }
                                            },
                                            "description": "Deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "deleted": true,
                                        "uid": "pub_9k2f3m1x"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The post is publishing right now.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope",
                                    "description": "See the referenced schema."
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This post is already publishing."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/{uid}/schedule": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostSchedule",
                "summary": "Schedule a post",
                "description": "Schedules a draft (or moves a pending scheduled post) to `at`. Pre-flight warnings must be accepted by code; errors answer 409 with the report.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The post id (pub_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pub_9k2f3m1x"
                    }
                ],
                "requestBody": {
                    "description": "The time.",
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "When.",
                                "required": [
                                    "at"
                                ],
                                "properties": {
                                    "at": {
                                        "type": "string",
                                        "description": "When to publish, ISO-8601."
                                    },
                                    "tz": {
                                        "type": "string",
                                        "description": "IANA timezone for `at`."
                                    },
                                    "accept_warnings": {
                                        "type": "array",
                                        "description": "Warning codes accepted.",
                                        "items": {
                                            "type": "string",
                                            "description": "A warning code."
                                        }
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "summary": "Example",
                                    "value": {
                                        "at": "2026-09-20T09:00:00",
                                        "tz": "Africa/Dar_es_Salaam",
                                        "accept_warnings": []
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Scheduled.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "post"
                                            ],
                                            "properties": {
                                                "post": {
                                                    "$ref": "#/components/schemas/Post",
                                                    "description": "The post in full."
                                                },
                                                "notice": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Anything the scheduler wants you to know."
                                                }
                                            },
                                            "description": "Scheduled."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "post": {
                                            "uid": "pub_9k2f3m1x",
                                            "status": "scheduled",
                                            "schedule_status": "pending",
                                            "scheduled_at": "2026-09-20T09:00:00+03:00",
                                            "scheduled_tz": "Africa/Dar_es_Salaam",
                                            "published_at": null,
                                            "completed_at": null,
                                            "created_at": "2026-09-18T10:12:00+03:00",
                                            "updated_at": "2026-09-18T10:15:00+03:00",
                                            "created_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_at": "2026-09-18T10:15:00+03:00",
                                            "content": {
                                                "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "media": [
                                                    {
                                                        "asset": "ast_7h3k2p",
                                                        "alt_text": "Chapati on a plate"
                                                    }
                                                ],
                                                "first_comment": "#chapati #dar"
                                            },
                                            "overrides": [],
                                            "options": {
                                                "tiktok": {
                                                    "privacy_level": "PUBLIC_TO_EVERYONE"
                                                }
                                            },
                                            "options_overrides": [],
                                            "targets": [
                                                {
                                                    "id": 31,
                                                    "social_account_id": 4,
                                                    "platform": "facebook",
                                                    "status": "pending",
                                                    "provider_post_id": null,
                                                    "permalink": null,
                                                    "error_message": null,
                                                    "published_at": null
                                                }
                                            ],
                                            "media": [
                                                {
                                                    "uid": "ast_7h3k2p",
                                                    "kind": "image",
                                                    "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                    "status": "ready"
                                                }
                                            ],
                                            "verification": {
                                                "errors": [],
                                                "warnings": []
                                            },
                                            "notes": null,
                                            "idempotency_key": "order-42",
                                            "approval": null
                                        },
                                        "notice": null
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The pre-flight blocked it, or the post is already publishing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope",
                                    "description": "See the referenced schema."
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This post has warnings to accept before it can be scheduled."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/{uid}/publish-now": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostPublishNow",
                "summary": "Publish a post now",
                "description": "Queues the post to go out immediately on every target. Same pre-flight rule as scheduling.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The post id (pub_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pub_9k2f3m1x"
                    }
                ],
                "requestBody": {
                    "description": "Accepted warnings, if any.",
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Accepted warnings.",
                                "properties": {
                                    "accept_warnings": {
                                        "type": "array",
                                        "description": "Warning codes accepted.",
                                        "items": {
                                            "type": "string",
                                            "description": "A warning code."
                                        }
                                    }
                                }
                            },
                            "examples": {
                                "default": {
                                    "summary": "Accepting one warning",
                                    "value": {
                                        "accept_warnings": [
                                            "caption_truncated"
                                        ]
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Publishing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "post"
                                            ],
                                            "properties": {
                                                "post": {
                                                    "$ref": "#/components/schemas/Post",
                                                    "description": "The post in full."
                                                }
                                            },
                                            "description": "Publishing."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "post": {
                                            "uid": "pub_9k2f3m1x",
                                            "status": "scheduled",
                                            "schedule_status": "pending",
                                            "scheduled_at": "2026-09-20T09:00:00+03:00",
                                            "scheduled_tz": "Africa/Dar_es_Salaam",
                                            "published_at": null,
                                            "completed_at": null,
                                            "created_at": "2026-09-18T10:12:00+03:00",
                                            "updated_at": "2026-09-18T10:15:00+03:00",
                                            "created_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_at": "2026-09-18T10:15:00+03:00",
                                            "content": {
                                                "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "media": [
                                                    {
                                                        "asset": "ast_7h3k2p",
                                                        "alt_text": "Chapati on a plate"
                                                    }
                                                ],
                                                "first_comment": "#chapati #dar"
                                            },
                                            "overrides": [],
                                            "options": {
                                                "tiktok": {
                                                    "privacy_level": "PUBLIC_TO_EVERYONE"
                                                }
                                            },
                                            "options_overrides": [],
                                            "targets": [
                                                {
                                                    "id": 31,
                                                    "social_account_id": 4,
                                                    "platform": "facebook",
                                                    "status": "pending",
                                                    "provider_post_id": null,
                                                    "permalink": null,
                                                    "error_message": null,
                                                    "published_at": null
                                                }
                                            ],
                                            "media": [
                                                {
                                                    "uid": "ast_7h3k2p",
                                                    "kind": "image",
                                                    "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                    "status": "ready"
                                                }
                                            ],
                                            "verification": {
                                                "errors": [],
                                                "warnings": []
                                            },
                                            "notes": null,
                                            "idempotency_key": "order-42",
                                            "approval": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The pre-flight blocked it, or the post is already publishing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope",
                                    "description": "See the referenced schema."
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This post is already publishing."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/posts/{uid}/cancel": {
            "post": {
                "tags": [
                    "Posts"
                ],
                "operationId": "v3PostCancel",
                "summary": "Cancel a scheduled post",
                "description": "Stops a scheduled post before its time: it is marked cancelled and will not go out. A post already publishing stops only the targets that have not started.",
                "x-permission": "posts.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The post id (pub_\u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "pub_9k2f3m1x"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Cancelled.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "post"
                                            ],
                                            "properties": {
                                                "post": {
                                                    "$ref": "#/components/schemas/Post",
                                                    "description": "The post in full."
                                                }
                                            },
                                            "description": "Cancelled."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "post": {
                                            "uid": "pub_9k2f3m1x",
                                            "status": "cancelled",
                                            "schedule_status": "processed",
                                            "scheduled_at": "2026-09-20T09:00:00+03:00",
                                            "scheduled_tz": "Africa/Dar_es_Salaam",
                                            "published_at": null,
                                            "completed_at": null,
                                            "created_at": "2026-09-18T10:12:00+03:00",
                                            "updated_at": "2026-09-18T10:15:00+03:00",
                                            "created_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_by": {
                                                "id": 12,
                                                "name": "Amina Juma"
                                            },
                                            "approved_at": "2026-09-18T10:15:00+03:00",
                                            "content": {
                                                "body": "Chapati za asubuhi zimeanza! Karibu Duka la Amina.",
                                                "media": [
                                                    {
                                                        "asset": "ast_7h3k2p",
                                                        "alt_text": "Chapati on a plate"
                                                    }
                                                ],
                                                "first_comment": "#chapati #dar"
                                            },
                                            "overrides": [],
                                            "options": {
                                                "tiktok": {
                                                    "privacy_level": "PUBLIC_TO_EVERYONE"
                                                }
                                            },
                                            "options_overrides": [],
                                            "targets": [
                                                {
                                                    "id": 31,
                                                    "social_account_id": 4,
                                                    "platform": "facebook",
                                                    "status": "pending",
                                                    "provider_post_id": null,
                                                    "permalink": null,
                                                    "error_message": null,
                                                    "published_at": null
                                                }
                                            ],
                                            "media": [
                                                {
                                                    "uid": "ast_7h3k2p",
                                                    "kind": "image",
                                                    "url": "https://business.momo.tz/storage/posts/ast_7h3k2p.jpg",
                                                    "status": "ready"
                                                }
                                            ],
                                            "verification": {
                                                "errors": [],
                                                "warnings": []
                                            },
                                            "notes": null,
                                            "idempotency_key": "order-42",
                                            "approval": null
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Nothing to cancel: the post is not scheduled.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope",
                                    "description": "See the referenced schema."
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This post is not scheduled."
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/occasions": {
            "get": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionList",
                "summary": "List the occasion cards",
                "description": "All 27 occasions, catalogue order, each with this workspace's decisions and inheritance applied. Not paginated \u2014 it is the whole calendar. Filters narrow it: `within_days=30` is \"coming up\", `enabled=true` is \"switched on\".",
                "x-permission": "communications.campaigns.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "category",
                        "in": "query",
                        "required": false,
                        "description": "One category only.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "tanzania",
                                "religious",
                                "world"
                            ]
                        },
                        "example": "religious"
                    },
                    {
                        "name": "enabled",
                        "in": "query",
                        "required": false,
                        "description": "Only switched-on (`true`) or switched-off (`false`) cards.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "true",
                                "false"
                            ]
                        },
                        "example": "true"
                    },
                    {
                        "name": "within_days",
                        "in": "query",
                        "required": false,
                        "description": "Only cards whose next date is at most this many days away. 0 is today.",
                        "schema": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 730
                        },
                        "example": 30
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Name search, English or Kiswahili, case-insensitive.",
                        "schema": {
                            "type": "string",
                            "maxLength": 80
                        },
                        "example": "idd"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The cards.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Occasion"
                                                    },
                                                    "description": "The cards, catalogue order."
                                                }
                                            },
                                            "description": "The list."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "key": "christmas-day",
                                                "name": "Christmas Day",
                                                "name_sw": "Krismasi",
                                                "category": "religious",
                                                "emoji": "\ud83c\udf84",
                                                "rule": "fixed",
                                                "is_public_holiday": true,
                                                "confidence": "certain",
                                                "caveat": null,
                                                "enabled": true,
                                                "customised": false,
                                                "message": "Merry Christmas, {{name}}! Wishing you peace and joy today, from all of us at {{store}}.",
                                                "language": "en",
                                                "send_time": "08:00",
                                                "sender_id": "DUKA",
                                                "contact_group_ids": [],
                                                "audience": "All customers",
                                                "inherited": [
                                                    "language",
                                                    "message",
                                                    "send_time",
                                                    "sender_id",
                                                    "contact_group_ids"
                                                ],
                                                "next_date": "2026-12-25",
                                                "next_date_label": "Fri, 25 Dec 2026",
                                                "days_until": 96,
                                                "date_override": null,
                                                "date_source": "calendar",
                                                "chars": 92,
                                                "segments": 1,
                                                "encoding": "GSM-7",
                                                "last_sent_on": null,
                                                "last_campaign": null,
                                                "updated_at": "2026-09-20T14:02:11+00:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    }
                }
            }
        },
        "/api/v3/occasions/catalogue": {
            "get": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionCatalogue",
                "summary": "The catalogue: when each occasion falls and what it says",
                "description": "Reference data with no workspace state: the rule behind each date, its next occurrence, how sure the calendar is, and the standard wording in both languages with what it costs. Keep this instead of your own calendar \u2014 the Islamic dates are moon-sighted, and the catalogue is the one copy that gets corrected.",
                "x-permission": "communications.campaigns.view",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "items"
                                            ],
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/OccasionCatalogueEntry"
                                                    },
                                                    "description": "Every occasion, catalogue order."
                                                }
                                            },
                                            "description": "The list."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "key": "eid-al-fitr",
                                                "name": "Eid al-Fitr",
                                                "name_sw": "Idd el-Fitr",
                                                "category": "religious",
                                                "emoji": "\ud83c\udf19",
                                                "rule": "table",
                                                "is_public_holiday": true,
                                                "commercial": true,
                                                "confidence": "approximate",
                                                "caveat": "The date follows the lunar calendar and is confirmed locally by moon sighting, so it can move by a day. Check it before the greeting goes out.",
                                                "next_date": "2027-03-09",
                                                "days_until": 170,
                                                "dates_known_until": "2030-02-04",
                                                "sms_en": "Eid Mubarak, {{name}}! Wishing you and your family a joyful Eid, from {{store}}. {{shop_url}}",
                                                "sms_sw": "Idd Mubarak, {{name}}! Tunakutakia wewe na familia yako Idd njema, kutoka {{store}}. {{shop_url}}",
                                                "segments_en": 1,
                                                "segments_sw": 1
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/occasions/settings": {
            "get": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionSettingsGet",
                "summary": "The workspace defaults, with the choices",
                "description": "What every card inherits unless it decided otherwise, and the sender IDs and contact groups it could be set to.",
                "x-permission": "communications.campaigns.view",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The defaults.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/OccasionSettings",
                                            "description": "The defaults, with the choices."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "sender_ids": [
                                            "DUKA"
                                        ],
                                        "sender_ids_available": [
                                            {
                                                "sender_id": "DUKA",
                                                "status": "approved"
                                            },
                                            {
                                                "sender_id": "SOKO",
                                                "status": "pending"
                                            }
                                        ],
                                        "contact_group_ids": [],
                                        "contact_groups": [
                                            {
                                                "id": 12,
                                                "name": "Wateja wa Dar",
                                                "contacts": 240
                                            }
                                        ],
                                        "send_time": "08:00",
                                        "language": "en"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "put": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionSettingsUpdate",
                "summary": "Change the workspace defaults",
                "description": "Only the fields sent are changed. Every card that inherits a changed field moves with it.",
                "x-permission": "communications.campaigns.manage",
                "x-permission-scope": "controller",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "sender_ids": {
                                        "type": "array",
                                        "items": {
                                            "type": "string",
                                            "description": "An approved sender ID of this workspace."
                                        },
                                        "description": "The sender IDs these greetings may use; each must be approved for this workspace. The first becomes the default."
                                    },
                                    "contact_group_ids": {
                                        "type": "array",
                                        "items": {
                                            "type": "integer",
                                            "description": "A contact group id of this workspace."
                                        },
                                        "description": "Default audience. Empty means every customer."
                                    },
                                    "send_time": {
                                        "type": "string",
                                        "pattern": "^\\d{2}:\\d{2}$",
                                        "description": "`HH:MM`, Africa/Dar_es_Salaam."
                                    },
                                    "language": {
                                        "type": "string",
                                        "enum": [
                                            "en",
                                            "sw"
                                        ],
                                        "description": "Default catalogue wording language."
                                    }
                                }
                            },
                            "example": {
                                "sender_ids": [
                                    "DUKA"
                                ],
                                "contact_group_ids": [
                                    12
                                ],
                                "send_time": "09:00",
                                "language": "sw"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The defaults after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/OccasionSettings",
                                            "description": "The defaults, with the choices."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "sender_ids": [
                                            "DUKA"
                                        ],
                                        "sender_ids_available": [
                                            {
                                                "sender_id": "DUKA",
                                                "status": "approved"
                                            },
                                            {
                                                "sender_id": "SOKO",
                                                "status": "pending"
                                            }
                                        ],
                                        "contact_group_ids": [
                                            12
                                        ],
                                        "contact_groups": [
                                            {
                                                "id": 12,
                                                "name": "Wateja wa Dar",
                                                "contacts": 240
                                            }
                                        ],
                                        "send_time": "09:00",
                                        "language": "sw"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    }
                }
            }
        },
        "/api/v3/occasions/preview": {
            "post": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionPreview",
                "summary": "What a message costs and how it reads",
                "description": "Measures any text the way a card is measured, so a composer can show the segment count as the customer types. `{{name}}`, `{{store}}`, `{{shop_url}}` and `{{year}}` are filled with samples in `rendered`.",
                "x-permission": "communications.campaigns.view",
                "x-permission-scope": "controller",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "message"
                                ],
                                "properties": {
                                    "message": {
                                        "type": "string",
                                        "maxLength": 800,
                                        "description": "The text to measure."
                                    }
                                }
                            },
                            "example": {
                                "message": "Heri ya Krismasi, {{name}}! Kutoka {{store}}."
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The measurement.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/OccasionPreview",
                                            "description": "The measurement."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "chars": 46,
                                        "segments": 1,
                                        "encoding": "GSM-7",
                                        "limit": 160,
                                        "rendered": "Heri ya Krismasi, Amina! Kutoka Duka la Amina."
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    }
                }
            }
        },
        "/api/v3/occasions/{key}": {
            "get": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionGet",
                "summary": "One card",
                "description": "The occasion's facts and this workspace's decisions about it, inheritance applied.",
                "x-permission": "communications.campaigns.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The occasion key (`christmas-day`, `eid-al-fitr`, \u2026), from `GET /api/v3/occasions` or `/api/v3/occasions/catalogue`.",
                        "schema": {
                            "type": "string",
                            "pattern": "^[a-z0-9-]+$"
                        },
                        "example": "christmas-day"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The card.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Occasion",
                                            "description": "The card."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "key": "christmas-day",
                                        "name": "Christmas Day",
                                        "name_sw": "Krismasi",
                                        "category": "religious",
                                        "emoji": "\ud83c\udf84",
                                        "rule": "fixed",
                                        "is_public_holiday": true,
                                        "confidence": "certain",
                                        "caveat": null,
                                        "enabled": true,
                                        "customised": false,
                                        "message": "Merry Christmas, {{name}}! Wishing you peace and joy today, from all of us at {{store}}.",
                                        "language": "en",
                                        "send_time": "08:00",
                                        "sender_id": "DUKA",
                                        "contact_group_ids": [],
                                        "audience": "All customers",
                                        "inherited": [
                                            "language",
                                            "message",
                                            "send_time",
                                            "sender_id",
                                            "contact_group_ids"
                                        ],
                                        "next_date": "2026-12-25",
                                        "next_date_label": "Fri, 25 Dec 2026",
                                        "days_until": 96,
                                        "date_override": null,
                                        "date_source": "calendar",
                                        "chars": 92,
                                        "segments": 1,
                                        "encoding": "GSM-7",
                                        "last_sent_on": null,
                                        "last_campaign": null,
                                        "updated_at": "2026-09-20T14:02:11+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "description": "No such occasion \u2014 the key is not in the catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OccasionRefusalEnvelope"
                                },
                                "examples": {
                                    "unknown": {
                                        "value": {
                                            "status": "error",
                                            "message": "No such occasion.",
                                            "code": "unknown_occasion"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
            "patch": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionUpdate",
                "summary": "Decide one card: its switch, wording, sender, audience, time, date",
                "description": "Partial. Only the fields sent change; a field sent as null returns to the default (see the body). Answers the card with inheritance re-applied.",
                "x-permission": "communications.campaigns.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The occasion key (`christmas-day`, `eid-al-fitr`, \u2026), from `GET /api/v3/occasions` or `/api/v3/occasions/catalogue`.",
                        "schema": {
                            "type": "string",
                            "pattern": "^[a-z0-9-]+$"
                        },
                        "example": "christmas-day"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Send only what changes. Every optional field accepts null, which clears the card's own value: `message` returns to the catalogue's wording, `language`/`send_time`/`sender_id`/`contact_group_ids` to the workspace default, `date_override` to the calendar. A value equal to the default is stored as inherited too.",
                                "properties": {
                                    "is_enabled": {
                                        "type": "boolean",
                                        "description": "Whether a greeting goes out on the day."
                                    },
                                    "message": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 800,
                                        "description": "Own wording. Placeholders: `{{name}}`, `{{store}}`, `{{shop_url}}`, `{{year}}`. Null: the catalogue's wording."
                                    },
                                    "language": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "enum": [
                                            "en",
                                            "sw",
                                            null
                                        ],
                                        "description": "Which catalogue wording to use. Null: the workspace default."
                                    },
                                    "send_time": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "pattern": "^\\d{2}:\\d{2}$",
                                        "description": "`HH:MM`, Africa/Dar_es_Salaam. Null: the workspace default."
                                    },
                                    "sender_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "description": "An approved sender ID of this workspace. Null: the workspace default."
                                    },
                                    "contact_group_ids": {
                                        "type": [
                                            "array",
                                            "null"
                                        ],
                                        "items": {
                                            "type": "integer",
                                            "description": "A contact group id of this workspace."
                                        },
                                        "description": "Who receives it. Empty or null: the workspace's default audience."
                                    },
                                    "date_override": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "date",
                                        "description": "Correct the calendar for the next occurrence (the moon was sighted a day later). Null: the calendar."
                                    }
                                }
                            },
                            "examples": {
                                "switchOn": {
                                    "summary": "Switch it on, everything else inherited",
                                    "value": {
                                        "is_enabled": true
                                    }
                                },
                                "customise": {
                                    "summary": "Own wording, own time, one group",
                                    "value": {
                                        "message": "Krismasi njema, {{name}}! Kutoka {{store}}.",
                                        "send_time": "18:00",
                                        "contact_group_ids": [
                                            12
                                        ]
                                    }
                                },
                                "clear": {
                                    "summary": "Back to the catalogue wording and the default time",
                                    "value": {
                                        "message": null,
                                        "send_time": null
                                    }
                                },
                                "moon": {
                                    "summary": "Eid was sighted a day later",
                                    "value": {
                                        "date_override": "2027-03-10"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The card after the change.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Occasion",
                                            "description": "The card."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "key": "christmas-day",
                                        "name": "Christmas Day",
                                        "name_sw": "Krismasi",
                                        "category": "religious",
                                        "emoji": "\ud83c\udf84",
                                        "rule": "fixed",
                                        "is_public_holiday": true,
                                        "confidence": "certain",
                                        "caveat": null,
                                        "enabled": true,
                                        "customised": false,
                                        "message": "Merry Christmas, {{name}}! Wishing you peace and joy today, from all of us at {{store}}.",
                                        "language": "en",
                                        "send_time": "08:00",
                                        "sender_id": "DUKA",
                                        "contact_group_ids": [],
                                        "audience": "All customers",
                                        "inherited": [
                                            "language",
                                            "message",
                                            "send_time",
                                            "sender_id",
                                            "contact_group_ids"
                                        ],
                                        "next_date": "2026-12-25",
                                        "next_date_label": "Fri, 25 Dec 2026",
                                        "days_until": 96,
                                        "date_override": null,
                                        "date_source": "calendar",
                                        "chars": 92,
                                        "segments": 1,
                                        "encoding": "GSM-7",
                                        "last_sent_on": null,
                                        "last_campaign": null,
                                        "updated_at": "2026-09-20T14:02:11+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "description": "No such occasion \u2014 the key is not in the catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OccasionRefusalEnvelope"
                                },
                                "examples": {
                                    "unknown": {
                                        "value": {
                                            "status": "error",
                                            "message": "No such occasion.",
                                            "code": "unknown_occasion"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionReset",
                "summary": "Reset a card to untouched",
                "description": "Off, the catalogue's wording, the workspace defaults, the calendar's date \u2014 as if nobody had ever opened it. Answers the reset card.",
                "x-permission": "communications.campaigns.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The occasion key (`christmas-day`, `eid-al-fitr`, \u2026), from `GET /api/v3/occasions` or `/api/v3/occasions/catalogue`.",
                        "schema": {
                            "type": "string",
                            "pattern": "^[a-z0-9-]+$"
                        },
                        "example": "christmas-day"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The card, untouched again.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Occasion",
                                            "description": "The card."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "key": "christmas-day",
                                        "name": "Christmas Day",
                                        "name_sw": "Krismasi",
                                        "category": "religious",
                                        "emoji": "\ud83c\udf84",
                                        "rule": "fixed",
                                        "is_public_holiday": true,
                                        "confidence": "certain",
                                        "caveat": null,
                                        "enabled": false,
                                        "customised": false,
                                        "message": "Merry Christmas, {{name}}! Wishing you peace and joy today, from all of us at {{store}}.",
                                        "language": "en",
                                        "send_time": "08:00",
                                        "sender_id": "DUKA",
                                        "contact_group_ids": [],
                                        "audience": "All customers",
                                        "inherited": [
                                            "language",
                                            "message",
                                            "send_time",
                                            "sender_id",
                                            "contact_group_ids"
                                        ],
                                        "next_date": "2026-12-25",
                                        "next_date_label": "Fri, 25 Dec 2026",
                                        "days_until": 96,
                                        "date_override": null,
                                        "date_source": "calendar",
                                        "chars": 92,
                                        "segments": 1,
                                        "encoding": "GSM-7",
                                        "last_sent_on": null,
                                        "last_campaign": null,
                                        "updated_at": "2026-09-20T14:02:11+00:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "description": "No such occasion \u2014 the key is not in the catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OccasionRefusalEnvelope"
                                },
                                "examples": {
                                    "unknown": {
                                        "value": {
                                            "status": "error",
                                            "message": "No such occasion.",
                                            "code": "unknown_occasion"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/occasions/{key}/send": {
            "post": {
                "tags": [
                    "Occasions"
                ],
                "operationId": "v3OccasionSendNow",
                "summary": "Send this greeting now",
                "description": "Today, whatever the calendar says \u2014 to the card's audience, from its sender, with its wording. Every chosen group is priced first, so the greeting is sent to all of them or refused whole. Money leaves on this call: send an `Idempotency-Key` header and a repeat replays the same answer. The campaign is created as the key's issuer; `campaign_uid` is what `GET /api/v3/campaign/{uid}/view` takes.",
                "x-permission": "communications.campaigns.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "key",
                        "in": "path",
                        "required": true,
                        "description": "The occasion key (`christmas-day`, `eid-al-fitr`, \u2026), from `GET /api/v3/occasions` or `/api/v3/occasions/catalogue`.",
                        "schema": {
                            "type": "string",
                            "pattern": "^[a-z0-9-]+$"
                        },
                        "example": "christmas-day"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters, unique per intended send. A repeat with the same key within 24 hours replays the first answer with `X-Idempotent-Replay: 1` and sends nothing.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "greeting-2026-12-25-001"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Sending.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "campaign_uid",
                                                "campaign_status",
                                                "occasion"
                                            ],
                                            "properties": {
                                                "campaign_uid": {
                                                    "type": "string",
                                                    "description": "The campaign this send created (`cmp_*`); steer it through the campaign endpoints."
                                                },
                                                "campaign_status": {
                                                    "type": "string",
                                                    "description": "`draft` while it queues; `running` once the first message leaves."
                                                },
                                                "occasion": {
                                                    "$ref": "#/components/schemas/Occasion",
                                                    "description": "The card, with `last_campaign` set."
                                                }
                                            },
                                            "description": "What was created."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "campaign_uid": "cmp_8d7f6g5h4j3k2l1m0n9b",
                                        "campaign_status": "draft",
                                        "occasion": {
                                            "key": "christmas-day",
                                            "name": "Christmas Day",
                                            "name_sw": "Krismasi",
                                            "category": "religious",
                                            "emoji": "\ud83c\udf84",
                                            "rule": "fixed",
                                            "is_public_holiday": true,
                                            "confidence": "certain",
                                            "caveat": null,
                                            "enabled": true,
                                            "customised": false,
                                            "message": "Merry Christmas, {{name}}! Wishing you peace and joy today, from all of us at {{store}}.",
                                            "language": "en",
                                            "send_time": "08:00",
                                            "sender_id": "DUKA",
                                            "contact_group_ids": [],
                                            "audience": "All customers",
                                            "inherited": [
                                                "language",
                                                "message",
                                                "send_time",
                                                "sender_id",
                                                "contact_group_ids"
                                            ],
                                            "next_date": "2026-12-25",
                                            "next_date_label": "Fri, 25 Dec 2026",
                                            "days_until": 96,
                                            "date_override": null,
                                            "date_source": "calendar",
                                            "chars": 92,
                                            "segments": 1,
                                            "encoding": "GSM-7",
                                            "last_sent_on": "2026-09-20",
                                            "last_campaign": {
                                                "uid": "cmp_8d7f6g5h4j3k2l1m0n9b",
                                                "status": "draft",
                                                "total_recipients": 0,
                                                "sent_count": 0,
                                                "failed_count": 0,
                                                "created_at": "2026-09-20T14:05:00+00:00"
                                            },
                                            "updated_at": "2026-09-20T14:02:11+00:00"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "description": "No such occasion \u2014 the key is not in the catalogue.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OccasionRefusalEnvelope"
                                },
                                "examples": {
                                    "unknown": {
                                        "value": {
                                            "status": "error",
                                            "message": "No such occasion.",
                                            "code": "unknown_occasion"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Refused, whole. See `code`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/OccasionRefusalEnvelope"
                                },
                                "examples": {
                                    "noMoney": {
                                        "summary": "Not enough balance for every chosen group",
                                        "value": {
                                            "status": "error",
                                            "message": "This greeting needs TZS 6,000.00 and TZS 1,250.00 is available.",
                                            "code": "insufficient_balance",
                                            "details": {
                                                "required": 6000,
                                                "balance": 1250,
                                                "currency": "TZS"
                                            }
                                        }
                                    },
                                    "nobody": {
                                        "summary": "The chosen groups have no contacts",
                                        "value": {
                                            "status": "error",
                                            "message": "Nobody to send to yet \u2014 the chosen contact groups have no contacts.",
                                            "code": "no_recipients"
                                        }
                                    },
                                    "noSender": {
                                        "summary": "No approved sender ID",
                                        "value": {
                                            "status": "error",
                                            "message": "Choose an approved sender ID for this greeting first.",
                                            "code": "no_sender"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms": {
            "get": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormList",
                "summary": "List forms",
                "description": "Forms in this workspace, newest first, with their state and answer counts. Retired forms are left out unless `status=retired` or `status=all`.",
                "x-permission": "forms.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "live",
                                "attention",
                                "retired",
                                "all"
                            ]
                        },
                        "description": "Only forms in this status: draft, live, attention or retired.",
                        "example": "live"
                    },
                    {
                        "name": "waba_id",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Only forms in this WhatsApp business account.",
                        "example": "102290129340398"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Free text over the name.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "miadi"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of forms.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppFormSummary"
                                                    },
                                                    "description": "The forms on this page, newest change first."
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page number, page size and totals."
                                                }
                                            },
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                                "name": "Weka miadi",
                                                "purpose": "APPOINTMENT_BOOKING",
                                                "status": "live",
                                                "live_version": 3,
                                                "meta_status": "PUBLISHED",
                                                "pages": 2,
                                                "questions": 7,
                                                "waba_id": "102290129340398",
                                                "data_table_id": null,
                                                "origin": "builder",
                                                "read_only": false,
                                                "answers": 418,
                                                "last_answer_at": "2026-09-25T09:12:00+00:00",
                                                "used_in": {
                                                    "flows": 2,
                                                    "templates": 0
                                                }
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormCreate",
                "summary": "Create a form",
                "description": "Creates a draft form in a WhatsApp Business Account (optional when the workspace has one). Nothing goes to WhatsApp until you publish; `issues` lists what would stop that. Send the whole `definition` or build it up with PATCH. With `menu_shop_id` instead, the form is that shop's menu inside WhatsApp: fixed screens, the shop's published products with their sizes and add-ons read live, and the answer is the order it became (`order_reference`, `order_total`, `items`, `note`).",
                "x-permission": "forms.create",
                "x-permission-scope": "controller",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "name"
                                ],
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 120,
                                        "description": "The form's name, as the Forms page shows it."
                                    },
                                    "purpose": {
                                        "type": "string",
                                        "description": "What the form is for, as WhatsApp asks: SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY or OTHER. It does not change how the form looks."
                                    },
                                    "waba_id": {
                                        "type": "string",
                                        "description": "`GET /api/v3/whatsapp/accounts` lists them."
                                    },
                                    "definition": {
                                        "$ref": "#/components/schemas/WhatsAppFormDefinition",
                                        "description": "The questions, page by page. See WhatsAppFormDefinition."
                                    },
                                    "settings": {
                                        "type": "object",
                                        "description": "Message text, button label, reply text, answerable hours, notify-on-answer, template id, phone number id and the Daftari column map. Only the keys sent are changed."
                                    },
                                    "menu_shop_id": {
                                        "type": "integer",
                                        "description": "Instead of a definition: make the form this shop's menu. Sizes and add-ons come from each product's options."
                                    },
                                    "menu_language": {
                                        "type": "string",
                                        "enum": [
                                            "sw",
                                            "en"
                                        ],
                                        "description": "With `menu_shop_id`: the language of the menu's own words. Default `sw`."
                                    },
                                    "accounts": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "maxItems": 20,
                                        "description": "More WhatsApp business account ids to publish the form on, besides `waba_id` (its home). Each gets its own copy of every version you publish, and a chat is sent the copy for the number it is on.",
                                        "example": [
                                            "209900112233445"
                                        ]
                                    }
                                }
                            },
                            "example": {
                                "name": "Weka miadi",
                                "purpose": "APPOINTMENT_BOOKING",
                                "definition": {
                                    "pages": [
                                        {
                                            "title": "Taarifa zako",
                                            "questions": [
                                                {
                                                    "key": "jina_kamili",
                                                    "type": "short_text",
                                                    "label": "Jina kamili",
                                                    "required": true
                                                },
                                                {
                                                    "key": "huduma",
                                                    "type": "dropdown",
                                                    "label": "Huduma",
                                                    "required": true,
                                                    "options": [
                                                        {
                                                            "key": "dental",
                                                            "label": "Kliniki ya meno"
                                                        },
                                                        {
                                                            "key": "lab",
                                                            "label": "Maabara"
                                                        }
                                                    ]
                                                }
                                            ]
                                        },
                                        {
                                            "title": "Muda",
                                            "questions": [
                                                {
                                                    "key": "tarehe",
                                                    "type": "date",
                                                    "label": "Tarehe",
                                                    "required": true
                                                },
                                                {
                                                    "key": "kadi",
                                                    "type": "photo",
                                                    "label": "Kadi ya bima"
                                                }
                                            ]
                                        }
                                    ],
                                    "submit_label": "Tuma"
                                },
                                "settings": {
                                    "message": "Karibu! Jaza fomu hii fupi.",
                                    "cta": "Weka miadi",
                                    "reply_text": "Asante! Tutakuthibitishia muda."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The new form.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppForm",
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "form": {
                                            "id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                            "name": "Weka miadi",
                                            "purpose": "APPOINTMENT_BOOKING",
                                            "status": "live",
                                            "live_version": 3,
                                            "meta_status": "PUBLISHED",
                                            "pages": 2,
                                            "questions": 4,
                                            "waba_id": "102290129340398",
                                            "data_table_id": null,
                                            "origin": "builder",
                                            "read_only": false,
                                            "definition": {
                                                "pages": [
                                                    {
                                                        "id": "SCREEN_A",
                                                        "title": "Taarifa zako",
                                                        "intro": null,
                                                        "questions": [
                                                            {
                                                                "key": "jina_kamili",
                                                                "type": "short_text",
                                                                "label": "Jina kamili",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false
                                                            },
                                                            {
                                                                "key": "huduma",
                                                                "type": "dropdown",
                                                                "label": "Huduma",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false,
                                                                "options": [
                                                                    {
                                                                        "key": "dental",
                                                                        "label": "Kliniki ya meno",
                                                                        "description": null
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    },
                                                    {
                                                        "id": "SCREEN_B",
                                                        "title": "Muda",
                                                        "intro": null,
                                                        "questions": [
                                                            {
                                                                "key": "tarehe",
                                                                "type": "date",
                                                                "label": "Tarehe",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false,
                                                                "min_date": null,
                                                                "max_date": null
                                                            },
                                                            {
                                                                "key": "kadi",
                                                                "type": "photo",
                                                                "label": "Kadi ya bima",
                                                                "help": null,
                                                                "required": false,
                                                                "sensitive": false,
                                                                "max_files": 2
                                                            }
                                                        ]
                                                    }
                                                ],
                                                "continue_label": "Endelea",
                                                "submit_label": "Tuma"
                                            },
                                            "settings": {
                                                "message": "Karibu! Jaza fomu hii fupi.",
                                                "cta": "Weka miadi",
                                                "reply_text": "Asante!",
                                                "notify_on_answer": false,
                                                "send_lifetime_hours": 72,
                                                "template_id": null,
                                                "phone_number_id": null,
                                                "data_map": []
                                            }
                                        },
                                        "versions": [
                                            {
                                                "number": 3,
                                                "state": "published",
                                                "meta_status": "PUBLISHED",
                                                "is_live": true,
                                                "published_at": "2026-09-24T08:00:00+00:00",
                                                "retire_after": null,
                                                "open_sends": 12
                                            }
                                        ],
                                        "stats": {
                                            "sent_30d": 1032,
                                            "answered_30d": 418,
                                            "answer_rate": 41,
                                            "median_seconds": 120,
                                            "answers_total": 418,
                                            "not_saved": 0
                                        },
                                        "used_in": {
                                            "flows": [
                                                {
                                                    "id": 7,
                                                    "name": "Karibu",
                                                    "status": "active",
                                                    "nodes": [
                                                        {
                                                            "id": "fomu",
                                                            "label": null
                                                        }
                                                    ]
                                                }
                                            ],
                                            "templates": []
                                        },
                                        "issues": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "409": {
                        "description": "No WhatsApp business account is connected.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "No WhatsApp business account is connected to this workspace. Connect one under Settings \u2192 WhatsApp first."
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/question-types": {
            "get": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormQuestionTypes",
                "summary": "What a question can be",
                "description": "Every question type with the WhatsApp component it becomes, the Daftari column its answers fit, and WhatsApp's limits (label length, number of choices).",
                "x-permission": "forms.view",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The catalog.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "question_types": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "Every question type with its WhatsApp component, the answer it produces and its limits."
                                                },
                                                "limits": {
                                                    "type": "object",
                                                    "description": "The limits the builder enforces (characters, options, pages)."
                                                },
                                                "purposes": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "object"
                                                    },
                                                    "description": "The purposes WhatsApp accepts, with their labels."
                                                }
                                            },
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "question_types": [
                                            {
                                                "type": "short_text",
                                                "label": "Short answer",
                                                "whatsapp_component": "TextInput",
                                                "daftari_column": "text",
                                                "has_options": false,
                                                "is_upload": false,
                                                "answer": "string",
                                                "label_limit": 20,
                                                "max_options": null,
                                                "hint": "One line of text."
                                            }
                                        ],
                                        "limits": {
                                            "pages": 10,
                                            "questions_per_page": 20
                                        },
                                        "purposes": [
                                            {
                                                "value": "APPOINTMENT_BOOKING",
                                                "label": "Appointment booking"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/{form}": {
            "get": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormShow",
                "summary": "Get a form",
                "description": "The form, its working copy (`form.definition`), settings, every version with its WhatsApp status, 30-day numbers, where it is used, and `issues`.",
                "x-permission": "forms.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The form.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppForm",
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "form": {
                                            "id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                            "name": "Weka miadi",
                                            "purpose": "APPOINTMENT_BOOKING",
                                            "status": "live",
                                            "live_version": 3,
                                            "meta_status": "PUBLISHED",
                                            "pages": 2,
                                            "questions": 4,
                                            "waba_id": "102290129340398",
                                            "data_table_id": null,
                                            "origin": "builder",
                                            "read_only": false,
                                            "definition": {
                                                "pages": [
                                                    {
                                                        "id": "SCREEN_A",
                                                        "title": "Taarifa zako",
                                                        "intro": null,
                                                        "questions": [
                                                            {
                                                                "key": "jina_kamili",
                                                                "type": "short_text",
                                                                "label": "Jina kamili",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false
                                                            },
                                                            {
                                                                "key": "huduma",
                                                                "type": "dropdown",
                                                                "label": "Huduma",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false,
                                                                "options": [
                                                                    {
                                                                        "key": "dental",
                                                                        "label": "Kliniki ya meno",
                                                                        "description": null
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    },
                                                    {
                                                        "id": "SCREEN_B",
                                                        "title": "Muda",
                                                        "intro": null,
                                                        "questions": [
                                                            {
                                                                "key": "tarehe",
                                                                "type": "date",
                                                                "label": "Tarehe",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false,
                                                                "min_date": null,
                                                                "max_date": null
                                                            },
                                                            {
                                                                "key": "kadi",
                                                                "type": "photo",
                                                                "label": "Kadi ya bima",
                                                                "help": null,
                                                                "required": false,
                                                                "sensitive": false,
                                                                "max_files": 2
                                                            }
                                                        ]
                                                    }
                                                ],
                                                "continue_label": "Endelea",
                                                "submit_label": "Tuma"
                                            },
                                            "settings": {
                                                "message": "Karibu! Jaza fomu hii fupi.",
                                                "cta": "Weka miadi",
                                                "reply_text": "Asante!",
                                                "notify_on_answer": false,
                                                "send_lifetime_hours": 72,
                                                "template_id": null,
                                                "phone_number_id": null,
                                                "data_map": []
                                            }
                                        },
                                        "versions": [
                                            {
                                                "number": 3,
                                                "state": "published",
                                                "meta_status": "PUBLISHED",
                                                "is_live": true,
                                                "published_at": "2026-09-24T08:00:00+00:00",
                                                "retire_after": null,
                                                "open_sends": 12
                                            }
                                        ],
                                        "stats": {
                                            "sent_30d": 1032,
                                            "answered_30d": 418,
                                            "answer_rate": 41,
                                            "median_seconds": 120,
                                            "answers_total": 418,
                                            "not_saved": 0
                                        },
                                        "used_in": {
                                            "flows": [
                                                {
                                                    "id": 7,
                                                    "name": "Karibu",
                                                    "status": "active",
                                                    "nodes": [
                                                        {
                                                            "id": "fomu",
                                                            "label": null
                                                        }
                                                    ]
                                                }
                                            ],
                                            "templates": []
                                        },
                                        "issues": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormUpdate",
                "summary": "Edit a form",
                "description": "Rename it, edit the working copy (`definition`, replaced whole) or change settings. A published version never changes: the edit becomes the next version when you publish. A question's key keeps its type once published.",
                "x-permission": "forms.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "The form's name, as the Forms page shows it."
                                    },
                                    "purpose": {
                                        "type": "string",
                                        "description": "What the form is for, as WhatsApp asks: SIGN_UP, SIGN_IN, APPOINTMENT_BOOKING, LEAD_GENERATION, CONTACT_US, CUSTOMER_SUPPORT, SURVEY or OTHER. It does not change how the form looks."
                                    },
                                    "definition": {
                                        "$ref": "#/components/schemas/WhatsAppFormDefinition",
                                        "description": "The questions, page by page. See WhatsAppFormDefinition."
                                    },
                                    "settings": {
                                        "type": "object",
                                        "description": "Message text, button label, reply text, answerable hours, notify-on-answer, template id, phone number id and the Daftari column map. Only the keys sent are changed."
                                    }
                                }
                            },
                            "example": {
                                "name": "Weka miadi (v2)",
                                "settings": {
                                    "cta": "Weka miadi",
                                    "reply_text": "Asante! Tutakuthibitishia muda."
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The form after the edit.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/WhatsAppForm",
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "form": {
                                            "id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                            "name": "Weka miadi",
                                            "purpose": "APPOINTMENT_BOOKING",
                                            "status": "live",
                                            "live_version": 3,
                                            "meta_status": "PUBLISHED",
                                            "pages": 2,
                                            "questions": 4,
                                            "waba_id": "102290129340398",
                                            "data_table_id": null,
                                            "origin": "builder",
                                            "read_only": false,
                                            "definition": {
                                                "pages": [
                                                    {
                                                        "id": "SCREEN_A",
                                                        "title": "Taarifa zako",
                                                        "intro": null,
                                                        "questions": [
                                                            {
                                                                "key": "jina_kamili",
                                                                "type": "short_text",
                                                                "label": "Jina kamili",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false
                                                            },
                                                            {
                                                                "key": "huduma",
                                                                "type": "dropdown",
                                                                "label": "Huduma",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false,
                                                                "options": [
                                                                    {
                                                                        "key": "dental",
                                                                        "label": "Kliniki ya meno",
                                                                        "description": null
                                                                    }
                                                                ]
                                                            }
                                                        ]
                                                    },
                                                    {
                                                        "id": "SCREEN_B",
                                                        "title": "Muda",
                                                        "intro": null,
                                                        "questions": [
                                                            {
                                                                "key": "tarehe",
                                                                "type": "date",
                                                                "label": "Tarehe",
                                                                "help": null,
                                                                "required": true,
                                                                "sensitive": false,
                                                                "min_date": null,
                                                                "max_date": null
                                                            },
                                                            {
                                                                "key": "kadi",
                                                                "type": "photo",
                                                                "label": "Kadi ya bima",
                                                                "help": null,
                                                                "required": false,
                                                                "sensitive": false,
                                                                "max_files": 2
                                                            }
                                                        ]
                                                    }
                                                ],
                                                "continue_label": "Endelea",
                                                "submit_label": "Tuma"
                                            },
                                            "settings": {
                                                "message": "Karibu! Jaza fomu hii fupi.",
                                                "cta": "Weka miadi",
                                                "reply_text": "Asante!",
                                                "notify_on_answer": false,
                                                "send_lifetime_hours": 72,
                                                "template_id": null,
                                                "phone_number_id": null,
                                                "data_map": []
                                            }
                                        },
                                        "versions": [
                                            {
                                                "number": 3,
                                                "state": "published",
                                                "meta_status": "PUBLISHED",
                                                "is_live": true,
                                                "published_at": "2026-09-24T08:00:00+00:00",
                                                "retire_after": null,
                                                "open_sends": 12
                                            }
                                        ],
                                        "stats": {
                                            "sent_30d": 1032,
                                            "answered_30d": 418,
                                            "answer_rate": 41,
                                            "median_seconds": 120,
                                            "answers_total": 418,
                                            "not_saved": 0
                                        },
                                        "used_in": {
                                            "flows": [
                                                {
                                                    "id": 7,
                                                    "name": "Karibu",
                                                    "status": "active",
                                                    "nodes": [
                                                        {
                                                            "id": "fomu",
                                                            "label": null
                                                        }
                                                    ]
                                                }
                                            ],
                                            "templates": []
                                        },
                                        "issues": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "409": {
                        "description": "The form was imported read-only.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This form was built outside Momo with parts the builder cannot edit; its definition cannot be changed here."
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/{form}/publish": {
            "post": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormPublish",
                "summary": "Publish a form",
                "description": "Uploads the working copy to WhatsApp, reads back WhatsApp's own checks and, when clean, publishes it as the next version. Flows switch to it at once, and it is published on every account the form was added to (each account's answer is in `accounts` on GET); the previous version keeps opening for customers who already have it, then retires. 422 carries `issues` (ours or WhatsApp's); 502 means WhatsApp could not be reached or refused.",
                "x-permission": "forms.publish",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Live.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "allOf": [
                                                {
                                                    "$ref": "#/components/schemas/WhatsAppFormSummary"
                                                },
                                                {
                                                    "type": "object",
                                                    "properties": {
                                                        "version": {
                                                            "type": "integer"
                                                        }
                                                    }
                                                }
                                            ],
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                        "name": "Weka miadi",
                                        "purpose": "APPOINTMENT_BOOKING",
                                        "status": "live",
                                        "live_version": 4,
                                        "meta_status": "PUBLISHED",
                                        "pages": 2,
                                        "questions": 4,
                                        "waba_id": "102290129340398",
                                        "data_table_id": null,
                                        "origin": "builder",
                                        "read_only": false,
                                        "version": 4
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "502": {
                        "description": "WhatsApp refused or could not be reached.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "WhatsApp refused the form: Flow JSON has invalid properties."
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/{form}/send": {
            "post": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormSend",
                "summary": "Send a form",
                "description": "Sends the live version to a phone number (`to`) or an existing conversation. Inside the 24-hour window it is a message with an Open form button; outside it, `template_id` must name an approved template with an Open form button for this form (409 otherwise). The answer comes back by webhook (`form.submitted`) and on `GET \u2026/answers`; `token` ties the two. The send is billed as a WhatsApp message.",
                "x-permission": "forms.send",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "description": "Phone number with country code, e.g. 255712345678."
                                    },
                                    "conversation_id": {
                                        "type": "integer",
                                        "description": "The WhatsApp conversation the form goes to. Pass this or `to`."
                                    },
                                    "body": {
                                        "type": "string",
                                        "maxLength": 1024,
                                        "description": "Defaults to the form's message."
                                    },
                                    "cta": {
                                        "type": "string",
                                        "maxLength": 20,
                                        "description": "The label on the button that opens the form (20 characters). Defaults to the form's own."
                                    },
                                    "template_id": {
                                        "type": "integer",
                                        "description": "Outside the 24-hour window: an approved template with an Open form button for this form. Without it such a send answers 409."
                                    },
                                    "reference": {
                                        "type": "string",
                                        "maxLength": 120,
                                        "description": "Your own reference, kept on the send."
                                    }
                                }
                            },
                            "example": {
                                "to": "255754118210",
                                "body": "Karibu Amina! Jaza fomu hii fupi.",
                                "cta": "Weka miadi"
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Queued to WhatsApp.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "send_id": {
                                                    "type": "integer",
                                                    "description": "The send's id."
                                                },
                                                "token": {
                                                    "type": "string",
                                                    "description": "The token the answer will carry back \u2014 the only link between a send and its answer."
                                                },
                                                "form_id": {
                                                    "type": "integer",
                                                    "description": "The form's id (uuid)."
                                                },
                                                "version_id": {
                                                    "type": "integer",
                                                    "description": "The form version that was sent."
                                                },
                                                "message_id": {
                                                    "type": "integer",
                                                    "description": "The WhatsApp message that carried the form."
                                                },
                                                "message_status": {
                                                    "type": "string",
                                                    "description": "The message's delivery status when the call returned."
                                                },
                                                "via": {
                                                    "type": "string",
                                                    "enum": [
                                                        "interactive",
                                                        "template"
                                                    ],
                                                    "description": "`interactive` inside the 24-hour window, `template` outside it."
                                                },
                                                "expires_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "When an answer to this send stops being accepted."
                                                },
                                                "conversation_id": {
                                                    "type": "integer",
                                                    "description": "The WhatsApp conversation the form goes to. Pass this or `to`."
                                                }
                                            },
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "send_id": 902,
                                        "token": "fm_k2j8x0q7m1d9s3v5b6n4c8z2a1",
                                        "form_id": 17,
                                        "version_id": 41,
                                        "message_id": 88231,
                                        "message_status": "sent",
                                        "via": "interactive",
                                        "expires_at": "2026-09-28T09:00:00+00:00",
                                        "conversation_id": 11893
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "409": {
                        "description": "The 24-hour window has closed and no template was named.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The 24-hour window has closed. Pick an approved template with an \"Open form\" button to reach this customer."
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/{form}/answers": {
            "get": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormAnswers",
                "summary": "List answers",
                "description": "Answers to this form, newest first. Page with `before` (the last id you saw; `next_before` in the answer). Test sends are left out. Photos and documents are named here and kept on the form.",
                "x-permission": "forms.answers.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    },
                    {
                        "name": "before",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "An answer id: return answers older than it (from next_before).",
                        "example": "1845"
                    },
                    {
                        "name": "since",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "description": "Only answers submitted at or after this time (ISO 8601).",
                        "example": "2026-09-26T08:00:00Z"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        },
                        "description": "How many answers per page, up to 100.",
                        "example": 50
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of answers.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppFormAnswer"
                                                    },
                                                    "description": "The result."
                                                },
                                                "next_before": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Pass as `before` to read the next (older) page; null on the last page."
                                                }
                                            },
                                            "description": "The result."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "data": [
                                            {
                                                "id": 5821,
                                                "form_id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                                "form_name": "Weka miadi",
                                                "version": 3,
                                                "source": "flow",
                                                "conversation_id": 11893,
                                                "contact": {
                                                    "name": "Amina Hassan",
                                                    "phone": "255754118210"
                                                },
                                                "answers": {
                                                    "jina_kamili": "Amina Hassan",
                                                    "huduma": "dental",
                                                    "tarehe": "2026-09-30",
                                                    "kadi": [
                                                        "kadi.jpg"
                                                    ]
                                                },
                                                "lines": [
                                                    {
                                                        "key": "huduma",
                                                        "label": "Huduma",
                                                        "value": "Kliniki ya meno"
                                                    }
                                                ],
                                                "files": [
                                                    {
                                                        "question": "kadi",
                                                        "file_name": "kadi.jpg",
                                                        "mime_type": "image/jpeg",
                                                        "size": 48211
                                                    }
                                                ],
                                                "record": {
                                                    "status": "skipped",
                                                    "id": null,
                                                    "error": null,
                                                    "table_id": null
                                                },
                                                "submitted_at": "2026-09-25T09:12:00+00:00"
                                            }
                                        ],
                                        "next_before": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/shop-links": {
            "post": {
                "tags": [
                    "Shop links and baskets"
                ],
                "operationId": "v3CreateShopLink",
                "summary": "Make or send a shop link",
                "description": "A link to your shop page \u2014 the menu, a `category`, or a product by `sku` \u2014 optionally with a basket already filled (`items`). With `conversation_id` or `to` (a phone number) it is sent into that WhatsApp chat as a link button, inside the 24-hour window (409 outside it); the basket the customer sends from the page comes back to that chat as an order. Sending needs `communications.send`. Without, you get a link to share; the customer finishes on WhatsApp or the order form.",
                "x-permission": "communications.catalogue.view",
                "x-permission-scope": "controller",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "shop_id": {
                                        "type": "integer",
                                        "description": "The shop; optional when the workspace has one shop page."
                                    },
                                    "category": {
                                        "type": "string",
                                        "description": "Open at this category \u2014 id or slug."
                                    },
                                    "sku": {
                                        "type": "string",
                                        "description": "Or open at this product."
                                    },
                                    "items": {
                                        "type": "array",
                                        "description": "Pre-fill the basket; the customer can change it.",
                                        "items": {
                                            "type": "object",
                                            "properties": {
                                                "sku": {
                                                    "type": "string",
                                                    "description": "The product SKU."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Or its name."
                                                },
                                                "variant": {
                                                    "type": "string",
                                                    "description": "The version name; the first in stock when omitted."
                                                },
                                                "addons": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Add-on names or ids."
                                                },
                                                "quantity": {
                                                    "type": "integer",
                                                    "description": "How many."
                                                },
                                                "note": {
                                                    "type": "string",
                                                    "description": "A note for the kitchen."
                                                }
                                            }
                                        }
                                    },
                                    "conversation_id": {
                                        "type": "integer",
                                        "description": "Send it into this WhatsApp chat."
                                    },
                                    "to": {
                                        "type": "string",
                                        "description": "Or send it to this number, country code first."
                                    },
                                    "message": {
                                        "type": "string",
                                        "description": "The text above the link button."
                                    },
                                    "cta": {
                                        "type": "string",
                                        "maxLength": 20,
                                        "description": "The button label."
                                    }
                                }
                            },
                            "example": {
                                "to": "255754118210",
                                "category": "vyakula",
                                "items": [
                                    {
                                        "sku": "ML-00001",
                                        "variant": "Kamili",
                                        "addons": [
                                            "Kachumbari"
                                        ],
                                        "quantity": 2
                                    }
                                ],
                                "message": "Karibu! Chagua chakula chako hapa."
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The link, and the basket behind it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The link.",
                                            "properties": {
                                                "url": {
                                                    "type": "string",
                                                    "description": "The link. A sent link is /w/{token} and answers back to the chat."
                                                },
                                                "sent": {
                                                    "type": "boolean",
                                                    "description": "True when it was sent to a chat."
                                                },
                                                "conversation_id": {
                                                    "type": "integer",
                                                    "description": "The chat it went to (when sent)."
                                                },
                                                "message_id": {
                                                    "type": "integer",
                                                    "description": "The message that carried it (when sent)."
                                                },
                                                "cart": {
                                                    "oneOf": [
                                                        {
                                                            "$ref": "#/components/schemas/Cart"
                                                        },
                                                        {
                                                            "type": "null"
                                                        }
                                                    ],
                                                    "description": "The basket behind the link, when there is one."
                                                },
                                                "problems": {
                                                    "type": "array",
                                                    "items": {
                                                        "type": "string"
                                                    },
                                                    "description": "Pre-fill lines that matched no product."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "url": "https://app.example.test/w/ct_4hx9q2m7r1t8v3y6b0n5c2k8d4f7g1a9",
                                        "sent": true,
                                        "conversation_id": 11893,
                                        "message_id": 774201,
                                        "cart": {
                                            "ref": "K7Q2M",
                                            "id": "9b2f4c1e-3a5d-4e8f-a1b2-c3d4e5f6a7b8",
                                            "code": "K7Q2M",
                                            "source": "storefront",
                                            "status": "open",
                                            "items": [
                                                {
                                                    "line_id": 3301,
                                                    "product_id": 812,
                                                    "sku": "ML-00001",
                                                    "retailer_id": "ML-00001",
                                                    "name": "Wali nyama",
                                                    "label": "Wali nyama \u00b7 Kamili (Kachumbari)",
                                                    "variant": "Kamili",
                                                    "variant_id": 44,
                                                    "options": [
                                                        {
                                                            "group": "Nyongeza",
                                                            "option": "Kachumbari",
                                                            "price_delta_minor": 50000
                                                        }
                                                    ],
                                                    "addon_ids": [
                                                        91
                                                    ],
                                                    "note": "Bila vitunguu",
                                                    "quantity": 2,
                                                    "unit_price_minor": 950000,
                                                    "line_total_minor": 1900000,
                                                    "currency": "TZS",
                                                    "image_url": null
                                                }
                                            ],
                                            "count": 1,
                                            "quantity": 2,
                                            "subtotal_minor": 1900000,
                                            "subtotal": "TSh 19,000",
                                            "currency": "TZS",
                                            "note": null,
                                            "conversation_id": 11893,
                                            "order_id": null,
                                            "order_reference": null,
                                            "shop": {
                                                "id": 7,
                                                "name": "Mama Lishe",
                                                "slug": "mama-lishe"
                                            },
                                            "expires_at": "2026-10-03T09:00:00Z"
                                        },
                                        "problems": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "409": {
                        "description": "The 24-hour window with this customer has closed; a free-form message cannot be sent.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "\"error\"."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "What went wrong."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The 24-hour window with this customer has closed, so a free-form message cannot be sent."
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/carts": {
            "get": {
                "tags": [
                    "Shop links and baskets"
                ],
                "operationId": "v3ListCarts",
                "summary": "List baskets",
                "description": "Baskets with something in them, newest first \u2014 by status, by chat, or both.",
                "x-permission": "communications.catalogue.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Only baskets in this status.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "open",
                                "sent",
                                "ordered",
                                "abandoned",
                                "expired"
                            ]
                        },
                        "example": "abandoned"
                    },
                    {
                        "name": "conversation_id",
                        "in": "query",
                        "required": false,
                        "description": "Only this chat's baskets.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 11893
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "How many, up to 100.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        },
                        "example": 25
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Baskets.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The result.",
                                            "properties": {
                                                "carts": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Cart"
                                                    },
                                                    "description": "Baskets, newest first."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "carts": [
                                            {
                                                "ref": "K7Q2M",
                                                "id": "9b2f4c1e-3a5d-4e8f-a1b2-c3d4e5f6a7b8",
                                                "code": "K7Q2M",
                                                "source": "storefront",
                                                "status": "ordered",
                                                "items": [
                                                    {
                                                        "line_id": 3301,
                                                        "product_id": 812,
                                                        "sku": "ML-00001",
                                                        "retailer_id": "ML-00001",
                                                        "name": "Wali nyama",
                                                        "label": "Wali nyama \u00b7 Kamili (Kachumbari)",
                                                        "variant": "Kamili",
                                                        "variant_id": 44,
                                                        "options": [
                                                            {
                                                                "group": "Nyongeza",
                                                                "option": "Kachumbari",
                                                                "price_delta_minor": 50000
                                                            }
                                                        ],
                                                        "addon_ids": [
                                                            91
                                                        ],
                                                        "note": "Bila vitunguu",
                                                        "quantity": 2,
                                                        "unit_price_minor": 950000,
                                                        "line_total_minor": 1900000,
                                                        "currency": "TZS",
                                                        "image_url": null
                                                    }
                                                ],
                                                "count": 1,
                                                "quantity": 2,
                                                "subtotal_minor": 1900000,
                                                "subtotal": "TSh 19,000",
                                                "currency": "TZS",
                                                "note": null,
                                                "conversation_id": 11893,
                                                "order_id": 1042,
                                                "order_reference": "#1042",
                                                "shop": {
                                                    "id": 7,
                                                    "name": "Mama Lishe",
                                                    "slug": "mama-lishe"
                                                },
                                                "expires_at": "2026-10-03T09:00:00Z"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/carts/{ref}": {
            "get": {
                "tags": [
                    "Shop links and baskets"
                ],
                "operationId": "v3GetCart",
                "summary": "Read a basket",
                "description": "One basket by its code (K7Q2M) or uuid: its lines with versions, add-ons, notes and prices, its status, its chat and the order it became.",
                "x-permission": "communications.catalogue.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "ref",
                        "in": "path",
                        "required": true,
                        "description": "The basket code or uuid.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "K7Q2M"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The basket.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The result.",
                                            "properties": {
                                                "cart": {
                                                    "allOf": [
                                                        {
                                                            "$ref": "#/components/schemas/Cart"
                                                        }
                                                    ],
                                                    "description": "The basket."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "cart": {
                                            "ref": "K7Q2M",
                                            "id": "9b2f4c1e-3a5d-4e8f-a1b2-c3d4e5f6a7b8",
                                            "code": "K7Q2M",
                                            "source": "storefront",
                                            "status": "ordered",
                                            "items": [
                                                {
                                                    "line_id": 3301,
                                                    "product_id": 812,
                                                    "sku": "ML-00001",
                                                    "retailer_id": "ML-00001",
                                                    "name": "Wali nyama",
                                                    "label": "Wali nyama \u00b7 Kamili (Kachumbari)",
                                                    "variant": "Kamili",
                                                    "variant_id": 44,
                                                    "options": [
                                                        {
                                                            "group": "Nyongeza",
                                                            "option": "Kachumbari",
                                                            "price_delta_minor": 50000
                                                        }
                                                    ],
                                                    "addon_ids": [
                                                        91
                                                    ],
                                                    "note": "Bila vitunguu",
                                                    "quantity": 2,
                                                    "unit_price_minor": 950000,
                                                    "line_total_minor": 1900000,
                                                    "currency": "TZS",
                                                    "image_url": null
                                                }
                                            ],
                                            "count": 1,
                                            "quantity": 2,
                                            "subtotal_minor": 1900000,
                                            "subtotal": "TSh 19,000",
                                            "currency": "TZS",
                                            "note": null,
                                            "conversation_id": 11893,
                                            "order_id": 1042,
                                            "order_reference": "#1042",
                                            "shop": {
                                                "id": 7,
                                                "name": "Mama Lishe",
                                                "slug": "mama-lishe"
                                            },
                                            "expires_at": "2026-10-03T09:00:00Z"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    }
                }
            }
        },
        "/api/v3/leads": {
            "get": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadList",
                "summary": "List leads",
                "description": "Leads the key may see, most recently active first. A key sees what its issuer sees: someone with `leads.data.all` sees every lead; anyone else sees the leads assigned to them, the unassigned pool, and the ones they added. Open leads only unless you ask for another `status`. Every list filter can be combined.",
                "x-permission": "leads.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "open (the default), closed (won, lost, unqualified), archived, or all.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "open",
                                "closed",
                                "archived",
                                "all"
                            ]
                        },
                        "example": "open"
                    },
                    {
                        "name": "stage",
                        "in": "query",
                        "required": false,
                        "description": "Only these stages, comma-separated.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "qualified,opportunity"
                    },
                    {
                        "name": "label",
                        "in": "query",
                        "required": false,
                        "description": "Only leads carrying one of these labels, by name or id, comma-separated.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "hot"
                    },
                    {
                        "name": "channel",
                        "in": "query",
                        "required": false,
                        "description": "Only leads that first came from these channels, comma-separated.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "whatsapp,call"
                    },
                    {
                        "name": "assigned_to",
                        "in": "query",
                        "required": false,
                        "description": "`me` (the key's issuer), `none` (the pool), or a team member id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "none"
                    },
                    {
                        "name": "created_by",
                        "in": "query",
                        "required": false,
                        "description": "Who added them: ai, people, api, user, mcp, flow, form, import or system.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "ai",
                                "people",
                                "user",
                                "mcp",
                                "api",
                                "flow",
                                "form",
                                "import",
                                "system"
                            ]
                        },
                        "example": "ai"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Free text over name, company and email; digits also match the phone.",
                        "schema": {
                            "type": "string",
                            "maxLength": 120
                        },
                        "example": "Amina"
                    },
                    {
                        "name": "date_field",
                        "in": "query",
                        "required": false,
                        "description": "Which date `from` and `to` filter: created (default) or last_activity.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "created",
                                "last_activity"
                            ]
                        },
                        "example": "created"
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "On or after this date.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "example": "2026-09-01"
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "On or before this date.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        },
                        "example": "2026-09-30"
                    },
                    {
                        "name": "updated_since",
                        "in": "query",
                        "required": false,
                        "description": "Only leads changed at or after this moment \u2014 for an incremental sync.",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "example": "2026-09-25T00:00:00+03:00"
                    },
                    {
                        "name": "score_min",
                        "in": "query",
                        "required": false,
                        "description": "Score at least this.",
                        "schema": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 100
                        },
                        "example": 60
                    },
                    {
                        "name": "score_max",
                        "in": "query",
                        "required": false,
                        "description": "Score at most this.",
                        "schema": {
                            "type": "integer",
                            "minimum": 0,
                            "maximum": 100
                        },
                        "example": 100
                    },
                    {
                        "name": "sort",
                        "in": "query",
                        "required": false,
                        "description": "Order by last_activity (default), created, value, score, next_action or name.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "last_activity",
                                "created",
                                "value",
                                "score",
                                "next_action",
                                "name"
                            ]
                        },
                        "example": "last_activity"
                    },
                    {
                        "name": "dir",
                        "in": "query",
                        "required": false,
                        "description": "desc (default) or asc.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "asc",
                                "desc"
                            ]
                        },
                        "example": "desc"
                    },
                    {
                        "$ref": "#/components/parameters/Limit"
                    },
                    {
                        "$ref": "#/components/parameters/Page"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The leads, most recently active first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "The leads on this page.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/LeadCard"
                                                    }
                                                },
                                                "pagination": {
                                                    "$ref": "#/components/schemas/Pagination",
                                                    "description": "Page state."
                                                }
                                            },
                                            "description": "The leads, most recently active first."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                                "name": "Amina Juma",
                                                "title": "Amina Juma",
                                                "company": "Amina Shop",
                                                "phone": "+255712345678",
                                                "email": null,
                                                "stage": "qualified",
                                                "stage_label": "Qualified",
                                                "closed": false,
                                                "archived": false,
                                                "labels": [
                                                    {
                                                        "id": 1,
                                                        "name": "hot",
                                                        "color": "#e11d48"
                                                    }
                                                ],
                                                "interest": "Solar kit 5 kW",
                                                "estimated_value": 4500000,
                                                "currency": "TZS",
                                                "score": 72,
                                                "source_channel": "whatsapp",
                                                "assigned_to": {
                                                    "id": 311,
                                                    "name": "Baraka M."
                                                },
                                                "next_action": "Send quote",
                                                "next_action_at": "2026-09-26T10:00:00+03:00",
                                                "overdue": false,
                                                "created_by": {
                                                    "kind": "ai",
                                                    "id": 14
                                                },
                                                "last_activity_at": "2026-09-25T14:03:11+03:00",
                                                "created_at": "2026-09-24T09:12:40+03:00"
                                            }
                                        ],
                                        "pagination": {
                                            "current_page": 1,
                                            "per_page": 25,
                                            "last_page": 1,
                                            "total": 1,
                                            "has_more_pages": false
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadUpsert",
                "summary": "Create or update a lead",
                "description": "An upsert, never a blind create. The person is found through the workspace's identity layer \u2014 a phone number, a WhatsApp id or an email all lead to the same person, and a `conversation_id` or `call_id` identifies them by that record \u2014 and their existing lead is updated (**200**); if they have none it is created (**201**). There is no way to make a second lead for one person. Empty values are ignored, so an upsert never blanks a field; clear a field with `PATCH`. A matched lead the key's issuer may not see answers **409** rather than revealing it.",
                "x-permission": "leads.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters. A repeat of a key whose call succeeded, within 24 hours, replays the first answer with `X-Idempotent-Replay: 1` and changes nothing. A refused call does not spend its key.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "crm-sync-2026-09-26-0042"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LeadInput"
                            },
                            "example": {
                                "name": "Grace Mushi",
                                "phone": "0754 221 908",
                                "company": "Mushi Hotels",
                                "interest": "IVR + 3 numbers",
                                "estimated_value": 6000000,
                                "labels": [
                                    "hot"
                                ],
                                "note": "Met at the Mlimani City fair."
                            }
                        }
                    },
                    "description": "The lead. Send at least one of phone, email or name \u2014 or a conversation_id / call_id."
                },
                "responses": {
                    "200": {
                        "description": "An existing lead matched and was updated.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/LeadCaptureResult",
                                            "description": "An existing lead matched and was updated."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "lead": {
                                            "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                            "name": "Amina Juma",
                                            "title": "Amina Juma",
                                            "company": "Amina Shop",
                                            "phone": "+255712345678",
                                            "email": null,
                                            "stage": "qualified",
                                            "stage_label": "Qualified",
                                            "closed": false,
                                            "archived": false,
                                            "labels": [
                                                {
                                                    "id": 1,
                                                    "name": "hot",
                                                    "color": "#e11d48"
                                                }
                                            ],
                                            "interest": "Solar kit 5 kW",
                                            "estimated_value": 4500000,
                                            "currency": "TZS",
                                            "score": 72,
                                            "source_channel": "whatsapp",
                                            "assigned_to": {
                                                "id": 311,
                                                "name": "Baraka M."
                                            },
                                            "next_action": "Send quote",
                                            "next_action_at": "2026-09-26T10:00:00+03:00",
                                            "overdue": false,
                                            "created_by": {
                                                "kind": "ai",
                                                "id": 14
                                            },
                                            "last_activity_at": "2026-09-25T14:03:11+03:00",
                                            "created_at": "2026-09-24T09:12:40+03:00",
                                            "location": "Mbezi, Dar es Salaam",
                                            "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                            "score_reason": "Budget stated, wants install this month",
                                            "source_detail": "Ad: October solar promo",
                                            "source_meta": {
                                                "ad_id": "120210000000001",
                                                "ad_headline": "October solar promo"
                                            },
                                            "lost_reason": null,
                                            "custom_fields": {
                                                "budget_band": "mid"
                                            },
                                            "missing_fields": [],
                                            "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                            "closed_at": null,
                                            "archived_at": null,
                                            "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                            "identities": [
                                                {
                                                    "kind": "whatsapp",
                                                    "value": "255712345678"
                                                },
                                                {
                                                    "kind": "phone",
                                                    "value": "255712345678"
                                                }
                                            ],
                                            "sources": [
                                                {
                                                    "kind": "conversation",
                                                    "id": "88213",
                                                    "channel": "whatsapp",
                                                    "title": "WhatsApp chat",
                                                    "url": "/app/communications/inbox?conversation=88213",
                                                    "is_origin": true,
                                                    "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                    "last_seen_at": "2026-09-25T14:03:11+03:00"
                                                },
                                                {
                                                    "kind": "call",
                                                    "id": "51007",
                                                    "channel": "call",
                                                    "title": "Call",
                                                    "url": "/app/calls/51007",
                                                    "call": {
                                                        "direction": "inbound",
                                                        "duration_seconds": 192,
                                                        "started_at": "2026-09-25T11:02:10+03:00",
                                                        "outcome": "answered",
                                                        "has_recording": true
                                                    },
                                                    "is_origin": false,
                                                    "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                    "last_seen_at": "2026-09-25T11:05:22+03:00"
                                                }
                                            ],
                                            "possible_duplicate": null
                                        },
                                        "created": false,
                                        "was_closed": false,
                                        "ignored": [],
                                        "refused": [],
                                        "possible_duplicate_of": null
                                    }
                                }
                            }
                        }
                    },
                    "201": {
                        "description": "A new lead was created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/LeadCaptureResult",
                                            "description": "A new lead was created."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "lead": {
                                            "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                            "name": "Amina Juma",
                                            "title": "Amina Juma",
                                            "company": "Amina Shop",
                                            "phone": "+255712345678",
                                            "email": null,
                                            "stage": "qualified",
                                            "stage_label": "Qualified",
                                            "closed": false,
                                            "archived": false,
                                            "labels": [
                                                {
                                                    "id": 1,
                                                    "name": "hot",
                                                    "color": "#e11d48"
                                                }
                                            ],
                                            "interest": "Solar kit 5 kW",
                                            "estimated_value": 4500000,
                                            "currency": "TZS",
                                            "score": 72,
                                            "source_channel": "whatsapp",
                                            "assigned_to": {
                                                "id": 311,
                                                "name": "Baraka M."
                                            },
                                            "next_action": "Send quote",
                                            "next_action_at": "2026-09-26T10:00:00+03:00",
                                            "overdue": false,
                                            "created_by": {
                                                "kind": "ai",
                                                "id": 14
                                            },
                                            "last_activity_at": "2026-09-25T14:03:11+03:00",
                                            "created_at": "2026-09-24T09:12:40+03:00",
                                            "location": "Mbezi, Dar es Salaam",
                                            "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                            "score_reason": "Budget stated, wants install this month",
                                            "source_detail": "Ad: October solar promo",
                                            "source_meta": {
                                                "ad_id": "120210000000001",
                                                "ad_headline": "October solar promo"
                                            },
                                            "lost_reason": null,
                                            "custom_fields": {
                                                "budget_band": "mid"
                                            },
                                            "missing_fields": [],
                                            "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                            "closed_at": null,
                                            "archived_at": null,
                                            "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                            "identities": [
                                                {
                                                    "kind": "whatsapp",
                                                    "value": "255712345678"
                                                },
                                                {
                                                    "kind": "phone",
                                                    "value": "255712345678"
                                                }
                                            ],
                                            "sources": [
                                                {
                                                    "kind": "conversation",
                                                    "id": "88213",
                                                    "channel": "whatsapp",
                                                    "title": "WhatsApp chat",
                                                    "url": "/app/communications/inbox?conversation=88213",
                                                    "is_origin": true,
                                                    "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                    "last_seen_at": "2026-09-25T14:03:11+03:00"
                                                },
                                                {
                                                    "kind": "call",
                                                    "id": "51007",
                                                    "channel": "call",
                                                    "title": "Call",
                                                    "url": "/app/calls/51007",
                                                    "call": {
                                                        "direction": "inbound",
                                                        "duration_seconds": 192,
                                                        "started_at": "2026-09-25T11:02:10+03:00",
                                                        "outcome": "answered",
                                                        "has_recording": true
                                                    },
                                                    "is_origin": false,
                                                    "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                    "last_seen_at": "2026-09-25T11:05:22+03:00"
                                                }
                                            ],
                                            "possible_duplicate": null
                                        },
                                        "created": true,
                                        "was_closed": false,
                                        "ignored": [],
                                        "refused": [
                                            {
                                                "label": "vip-gold",
                                                "reason": "label_unknown"
                                            }
                                        ],
                                        "possible_duplicate_of": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "409": {
                        "description": "The person already has a lead that the key's issuer may not see.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This person is already a lead that the key's issuer cannot see. Ask a manager to assign it, or use a key issued by someone who sees every lead.",
                                    "reason": "owned_elsewhere"
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/leads/{lead}": {
            "get": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadShow",
                "summary": "Read a lead",
                "description": "One lead, with its identities, the records it is attached to (origin first) and a possible duplicate.",
                "x-permission": "leads.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The lead.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Lead",
                                            "description": "The lead."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                        "name": "Amina Juma",
                                        "title": "Amina Juma",
                                        "company": "Amina Shop",
                                        "phone": "+255712345678",
                                        "email": null,
                                        "stage": "qualified",
                                        "stage_label": "Qualified",
                                        "closed": false,
                                        "archived": false,
                                        "labels": [
                                            {
                                                "id": 1,
                                                "name": "hot",
                                                "color": "#e11d48"
                                            }
                                        ],
                                        "interest": "Solar kit 5 kW",
                                        "estimated_value": 4500000,
                                        "currency": "TZS",
                                        "score": 72,
                                        "source_channel": "whatsapp",
                                        "assigned_to": {
                                            "id": 311,
                                            "name": "Baraka M."
                                        },
                                        "next_action": "Send quote",
                                        "next_action_at": "2026-09-26T10:00:00+03:00",
                                        "overdue": false,
                                        "created_by": {
                                            "kind": "ai",
                                            "id": 14
                                        },
                                        "last_activity_at": "2026-09-25T14:03:11+03:00",
                                        "created_at": "2026-09-24T09:12:40+03:00",
                                        "location": "Mbezi, Dar es Salaam",
                                        "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                        "score_reason": "Budget stated, wants install this month",
                                        "source_detail": "Ad: October solar promo",
                                        "source_meta": {
                                            "ad_id": "120210000000001",
                                            "ad_headline": "October solar promo"
                                        },
                                        "lost_reason": null,
                                        "custom_fields": {
                                            "budget_band": "mid"
                                        },
                                        "missing_fields": [],
                                        "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                        "closed_at": null,
                                        "archived_at": null,
                                        "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                        "identities": [
                                            {
                                                "kind": "whatsapp",
                                                "value": "255712345678"
                                            },
                                            {
                                                "kind": "phone",
                                                "value": "255712345678"
                                            }
                                        ],
                                        "sources": [
                                            {
                                                "kind": "conversation",
                                                "id": "88213",
                                                "channel": "whatsapp",
                                                "title": "WhatsApp chat",
                                                "url": "/app/communications/inbox?conversation=88213",
                                                "is_origin": true,
                                                "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                "last_seen_at": "2026-09-25T14:03:11+03:00"
                                            },
                                            {
                                                "kind": "call",
                                                "id": "51007",
                                                "channel": "call",
                                                "title": "Call",
                                                "url": "/app/calls/51007",
                                                "call": {
                                                    "direction": "inbound",
                                                    "duration_seconds": 192,
                                                    "started_at": "2026-09-25T11:02:10+03:00",
                                                    "outcome": "answered",
                                                    "has_recording": true
                                                },
                                                "is_origin": false,
                                                "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                "last_seen_at": "2026-09-25T11:05:22+03:00"
                                            }
                                        ],
                                        "possible_duplicate": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "patch": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadUpdate",
                "summary": "Change a lead's fields",
                "description": "Send only the fields to change. `null` or `\"\"` clears a field. A new phone or email is filed against the person, so the next time they call or write from it they are recognised. The stage is not changed here \u2014 use `POST /leads/{lead}/stage`, because lost and unqualified need a reason.",
                "x-permission": "leads.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Fields to change.",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "The person's name.",
                                        "maxLength": 160
                                    },
                                    "phone": {
                                        "type": "string",
                                        "description": "Their phone number in any common form \u2014 0712 345 678, 712345678, +255 712 345 678. Stored as E.164.",
                                        "maxLength": 40
                                    },
                                    "email": {
                                        "type": "string",
                                        "description": "Their email address.",
                                        "maxLength": 191
                                    },
                                    "company": {
                                        "type": "string",
                                        "description": "Their business.",
                                        "maxLength": 160
                                    },
                                    "location": {
                                        "type": "string",
                                        "description": "Area or city.",
                                        "maxLength": 160
                                    },
                                    "interest": {
                                        "type": "string",
                                        "description": "What they want to buy.",
                                        "maxLength": 255
                                    },
                                    "estimated_value": {
                                        "type": "number",
                                        "description": "Expected deal size in the currency's main unit (4500000 = TSh 4.5M).",
                                        "minimum": 0
                                    },
                                    "currency": {
                                        "type": "string",
                                        "description": "ISO 4217 code, e.g. TZS. Defaults to the workspace's currency.",
                                        "minLength": 3,
                                        "maxLength": 3
                                    },
                                    "score": {
                                        "type": "integer",
                                        "description": "How likely they are to buy, 0\u2013100.",
                                        "minimum": 0,
                                        "maximum": 100
                                    },
                                    "score_reason": {
                                        "type": "string",
                                        "description": "Why that score.",
                                        "maxLength": 500
                                    },
                                    "summary": {
                                        "type": "string",
                                        "description": "A short account of what they need.",
                                        "maxLength": 1000
                                    },
                                    "next_action": {
                                        "type": "string",
                                        "description": "The next thing to do.",
                                        "maxLength": 255
                                    },
                                    "next_action_at": {
                                        "type": "string",
                                        "description": "When it is due, ISO 8601. A time with no offset is read in the workspace's timezone.",
                                        "format": "date-time"
                                    },
                                    "source_detail": {
                                        "type": "string",
                                        "description": "A human line about where the lead came from, e.g. \"Trade fair, Mlimani City\".",
                                        "maxLength": 255
                                    },
                                    "custom_fields": {
                                        "type": "object",
                                        "description": "Custom field values keyed by field key from `GET /api/v3/lead-fields`.",
                                        "additionalProperties": true
                                    }
                                }
                            },
                            "example": {
                                "interest": "Business line, 10 numbers",
                                "next_action": "Call back",
                                "next_action_at": "2026-09-27T10:00:00+03:00",
                                "company": null
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The lead as it is now.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Lead",
                                            "description": "The lead as it is now."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                        "name": "Amina Juma",
                                        "title": "Amina Juma",
                                        "company": "Amina Shop",
                                        "phone": "+255712345678",
                                        "email": null,
                                        "stage": "qualified",
                                        "stage_label": "Qualified",
                                        "closed": false,
                                        "archived": false,
                                        "labels": [
                                            {
                                                "id": 1,
                                                "name": "hot",
                                                "color": "#e11d48"
                                            }
                                        ],
                                        "interest": "Solar kit 5 kW",
                                        "estimated_value": 4500000,
                                        "currency": "TZS",
                                        "score": 72,
                                        "source_channel": "whatsapp",
                                        "assigned_to": {
                                            "id": 311,
                                            "name": "Baraka M."
                                        },
                                        "next_action": "Send quote",
                                        "next_action_at": "2026-09-26T10:00:00+03:00",
                                        "overdue": false,
                                        "created_by": {
                                            "kind": "ai",
                                            "id": 14
                                        },
                                        "last_activity_at": "2026-09-25T14:03:11+03:00",
                                        "created_at": "2026-09-24T09:12:40+03:00",
                                        "location": "Mbezi, Dar es Salaam",
                                        "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                        "score_reason": "Budget stated, wants install this month",
                                        "source_detail": "Ad: October solar promo",
                                        "source_meta": {
                                            "ad_id": "120210000000001",
                                            "ad_headline": "October solar promo"
                                        },
                                        "lost_reason": null,
                                        "custom_fields": {
                                            "budget_band": "mid"
                                        },
                                        "missing_fields": [],
                                        "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                        "closed_at": null,
                                        "archived_at": null,
                                        "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                        "identities": [
                                            {
                                                "kind": "whatsapp",
                                                "value": "255712345678"
                                            },
                                            {
                                                "kind": "phone",
                                                "value": "255712345678"
                                            }
                                        ],
                                        "sources": [
                                            {
                                                "kind": "conversation",
                                                "id": "88213",
                                                "channel": "whatsapp",
                                                "title": "WhatsApp chat",
                                                "url": "/app/communications/inbox?conversation=88213",
                                                "is_origin": true,
                                                "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                "last_seen_at": "2026-09-25T14:03:11+03:00"
                                            },
                                            {
                                                "kind": "call",
                                                "id": "51007",
                                                "channel": "call",
                                                "title": "Call",
                                                "url": "/app/calls/51007",
                                                "call": {
                                                    "direction": "inbound",
                                                    "duration_seconds": 192,
                                                    "started_at": "2026-09-25T11:02:10+03:00",
                                                    "outcome": "answered",
                                                    "has_recording": true
                                                },
                                                "is_origin": false,
                                                "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                "last_seen_at": "2026-09-25T11:05:22+03:00"
                                            }
                                        ],
                                        "possible_duplicate": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadDelete",
                "summary": "Delete a lead",
                "description": "Removes the lead. Its history stays on record, and the person can get a new lead later. Sends `lead.deleted` to webhooks that subscribe.",
                "x-permission": "leads.delete",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The lead was deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "string",
                                                    "description": "The deleted lead's id.",
                                                    "format": "uuid"
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                }
                                            },
                                            "description": "The lead was deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                        "deleted": true
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/leads/{lead}/stage": {
            "post": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadStage",
                "summary": "Move a lead to another stage",
                "description": "won, lost and unqualified close the lead; moving out of them reopens it. lost and unqualified need a `reason` (refused with reason `reason_required` otherwise).",
                "x-permission": "leads.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters. A repeat of a key whose call succeeded, within 24 hours, replays the first answer with `X-Idempotent-Replay: 1` and changes nothing. A refused call does not spend its key.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "crm-sync-2026-09-26-0042"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "stage"
                                ],
                                "properties": {
                                    "stage": {
                                        "type": "string",
                                        "description": "The new stage.",
                                        "enum": [
                                            "new",
                                            "contacted",
                                            "qualified",
                                            "opportunity",
                                            "won",
                                            "lost",
                                            "unqualified"
                                        ]
                                    },
                                    "reason": {
                                        "type": "string",
                                        "description": "Why \u2014 required for lost and unqualified.",
                                        "maxLength": 255
                                    }
                                }
                            },
                            "example": {
                                "stage": "lost",
                                "reason": "Bought from a competitor"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The lead in its new stage.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Lead",
                                            "description": "The lead in its new stage."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                        "name": "Amina Juma",
                                        "title": "Amina Juma",
                                        "company": "Amina Shop",
                                        "phone": "+255712345678",
                                        "email": null,
                                        "stage": "lost",
                                        "stage_label": "Lost",
                                        "closed": true,
                                        "archived": false,
                                        "labels": [
                                            {
                                                "id": 1,
                                                "name": "hot",
                                                "color": "#e11d48"
                                            }
                                        ],
                                        "interest": "Solar kit 5 kW",
                                        "estimated_value": 4500000,
                                        "currency": "TZS",
                                        "score": 72,
                                        "source_channel": "whatsapp",
                                        "assigned_to": {
                                            "id": 311,
                                            "name": "Baraka M."
                                        },
                                        "next_action": "Send quote",
                                        "next_action_at": "2026-09-26T10:00:00+03:00",
                                        "overdue": false,
                                        "created_by": {
                                            "kind": "ai",
                                            "id": 14
                                        },
                                        "last_activity_at": "2026-09-25T14:03:11+03:00",
                                        "created_at": "2026-09-24T09:12:40+03:00",
                                        "location": "Mbezi, Dar es Salaam",
                                        "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                        "score_reason": "Budget stated, wants install this month",
                                        "source_detail": "Ad: October solar promo",
                                        "source_meta": {
                                            "ad_id": "120210000000001",
                                            "ad_headline": "October solar promo"
                                        },
                                        "lost_reason": "Bought from a competitor",
                                        "custom_fields": {
                                            "budget_band": "mid"
                                        },
                                        "missing_fields": [],
                                        "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                        "closed_at": "2026-09-25T14:03:11+03:00",
                                        "archived_at": null,
                                        "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                        "identities": [
                                            {
                                                "kind": "whatsapp",
                                                "value": "255712345678"
                                            },
                                            {
                                                "kind": "phone",
                                                "value": "255712345678"
                                            }
                                        ],
                                        "sources": [
                                            {
                                                "kind": "conversation",
                                                "id": "88213",
                                                "channel": "whatsapp",
                                                "title": "WhatsApp chat",
                                                "url": "/app/communications/inbox?conversation=88213",
                                                "is_origin": true,
                                                "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                "last_seen_at": "2026-09-25T14:03:11+03:00"
                                            },
                                            {
                                                "kind": "call",
                                                "id": "51007",
                                                "channel": "call",
                                                "title": "Call",
                                                "url": "/app/calls/51007",
                                                "call": {
                                                    "direction": "inbound",
                                                    "duration_seconds": 192,
                                                    "started_at": "2026-09-25T11:02:10+03:00",
                                                    "outcome": "answered",
                                                    "has_recording": true
                                                },
                                                "is_origin": false,
                                                "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                "last_seen_at": "2026-09-25T11:05:22+03:00"
                                            }
                                        ],
                                        "possible_duplicate": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/leads/{lead}/labels": {
            "post": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadLabelsAdd",
                "summary": "Add labels to a lead",
                "description": "By name, matched regardless of case. A name that does not exist yet is created if the key's issuer holds `leads.settings`, and otherwise comes back in `refused`. Labels already on the lead are left alone.",
                "x-permission": "leads.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters. A repeat of a key whose call succeeded, within 24 hours, replays the first answer with `X-Idempotent-Replay: 1` and changes nothing. A refused call does not spend its key.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "crm-sync-2026-09-26-0042"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "labels"
                                ],
                                "properties": {
                                    "labels": {
                                        "type": "array",
                                        "description": "Label names, matched regardless of case.",
                                        "minItems": 1,
                                        "items": {
                                            "type": "string",
                                            "maxLength": 64
                                        }
                                    }
                                }
                            },
                            "example": {
                                "labels": [
                                    "hot",
                                    "follow-up"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The lead with its labels, and any that were refused.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "lead": {
                                                    "$ref": "#/components/schemas/Lead",
                                                    "description": "The lead with its labels as they are now."
                                                },
                                                "refused": {
                                                    "type": "array",
                                                    "description": "Labels that were not applied, and why.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One refused label.",
                                                        "properties": {
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The label name."
                                                            },
                                                            "reason": {
                                                                "type": "string",
                                                                "description": "label_unknown or label_not_available."
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "description": "The lead with its labels, and any that were refused."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "lead": {
                                            "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                            "name": "Amina Juma",
                                            "title": "Amina Juma",
                                            "company": "Amina Shop",
                                            "phone": "+255712345678",
                                            "email": null,
                                            "stage": "qualified",
                                            "stage_label": "Qualified",
                                            "closed": false,
                                            "archived": false,
                                            "labels": [
                                                {
                                                    "id": 1,
                                                    "name": "hot",
                                                    "color": "#e11d48"
                                                }
                                            ],
                                            "interest": "Solar kit 5 kW",
                                            "estimated_value": 4500000,
                                            "currency": "TZS",
                                            "score": 72,
                                            "source_channel": "whatsapp",
                                            "assigned_to": {
                                                "id": 311,
                                                "name": "Baraka M."
                                            },
                                            "next_action": "Send quote",
                                            "next_action_at": "2026-09-26T10:00:00+03:00",
                                            "overdue": false,
                                            "created_by": {
                                                "kind": "ai",
                                                "id": 14
                                            },
                                            "last_activity_at": "2026-09-25T14:03:11+03:00",
                                            "created_at": "2026-09-24T09:12:40+03:00",
                                            "location": "Mbezi, Dar es Salaam",
                                            "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                            "score_reason": "Budget stated, wants install this month",
                                            "source_detail": "Ad: October solar promo",
                                            "source_meta": {
                                                "ad_id": "120210000000001",
                                                "ad_headline": "October solar promo"
                                            },
                                            "lost_reason": null,
                                            "custom_fields": {
                                                "budget_band": "mid"
                                            },
                                            "missing_fields": [],
                                            "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                            "closed_at": null,
                                            "archived_at": null,
                                            "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                            "identities": [
                                                {
                                                    "kind": "whatsapp",
                                                    "value": "255712345678"
                                                },
                                                {
                                                    "kind": "phone",
                                                    "value": "255712345678"
                                                }
                                            ],
                                            "sources": [
                                                {
                                                    "kind": "conversation",
                                                    "id": "88213",
                                                    "channel": "whatsapp",
                                                    "title": "WhatsApp chat",
                                                    "url": "/app/communications/inbox?conversation=88213",
                                                    "is_origin": true,
                                                    "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                    "last_seen_at": "2026-09-25T14:03:11+03:00"
                                                },
                                                {
                                                    "kind": "call",
                                                    "id": "51007",
                                                    "channel": "call",
                                                    "title": "Call",
                                                    "url": "/app/calls/51007",
                                                    "call": {
                                                        "direction": "inbound",
                                                        "duration_seconds": 192,
                                                        "started_at": "2026-09-25T11:02:10+03:00",
                                                        "outcome": "answered",
                                                        "has_recording": true
                                                    },
                                                    "is_origin": false,
                                                    "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                    "last_seen_at": "2026-09-25T11:05:22+03:00"
                                                }
                                            ],
                                            "possible_duplicate": null
                                        },
                                        "refused": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadLabelsRemove",
                "summary": "Remove labels from a lead",
                "description": "By name. Names the lead does not carry are ignored. The names may also be sent as `?labels=hot,warm`.",
                "x-permission": "leads.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "labels"
                                ],
                                "properties": {
                                    "labels": {
                                        "type": "array",
                                        "description": "Label names, matched regardless of case.",
                                        "minItems": 1,
                                        "items": {
                                            "type": "string",
                                            "maxLength": 64
                                        }
                                    }
                                }
                            },
                            "example": {
                                "labels": [
                                    "cold"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The lead with its remaining labels.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "lead": {
                                                    "$ref": "#/components/schemas/Lead",
                                                    "description": "The lead with its labels as they are now."
                                                },
                                                "refused": {
                                                    "type": "array",
                                                    "description": "Labels that were not applied, and why.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One refused label.",
                                                        "properties": {
                                                            "label": {
                                                                "type": "string",
                                                                "description": "The label name."
                                                            },
                                                            "reason": {
                                                                "type": "string",
                                                                "description": "label_unknown or label_not_available."
                                                            }
                                                        }
                                                    }
                                                }
                                            },
                                            "description": "The lead with its remaining labels."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "lead": {
                                            "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                            "name": "Amina Juma",
                                            "title": "Amina Juma",
                                            "company": "Amina Shop",
                                            "phone": "+255712345678",
                                            "email": null,
                                            "stage": "qualified",
                                            "stage_label": "Qualified",
                                            "closed": false,
                                            "archived": false,
                                            "labels": [
                                                {
                                                    "id": 1,
                                                    "name": "hot",
                                                    "color": "#e11d48"
                                                }
                                            ],
                                            "interest": "Solar kit 5 kW",
                                            "estimated_value": 4500000,
                                            "currency": "TZS",
                                            "score": 72,
                                            "source_channel": "whatsapp",
                                            "assigned_to": {
                                                "id": 311,
                                                "name": "Baraka M."
                                            },
                                            "next_action": "Send quote",
                                            "next_action_at": "2026-09-26T10:00:00+03:00",
                                            "overdue": false,
                                            "created_by": {
                                                "kind": "ai",
                                                "id": 14
                                            },
                                            "last_activity_at": "2026-09-25T14:03:11+03:00",
                                            "created_at": "2026-09-24T09:12:40+03:00",
                                            "location": "Mbezi, Dar es Salaam",
                                            "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                            "score_reason": "Budget stated, wants install this month",
                                            "source_detail": "Ad: October solar promo",
                                            "source_meta": {
                                                "ad_id": "120210000000001",
                                                "ad_headline": "October solar promo"
                                            },
                                            "lost_reason": null,
                                            "custom_fields": {
                                                "budget_band": "mid"
                                            },
                                            "missing_fields": [],
                                            "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                            "closed_at": null,
                                            "archived_at": null,
                                            "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                            "identities": [
                                                {
                                                    "kind": "whatsapp",
                                                    "value": "255712345678"
                                                },
                                                {
                                                    "kind": "phone",
                                                    "value": "255712345678"
                                                }
                                            ],
                                            "sources": [
                                                {
                                                    "kind": "conversation",
                                                    "id": "88213",
                                                    "channel": "whatsapp",
                                                    "title": "WhatsApp chat",
                                                    "url": "/app/communications/inbox?conversation=88213",
                                                    "is_origin": true,
                                                    "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                    "last_seen_at": "2026-09-25T14:03:11+03:00"
                                                },
                                                {
                                                    "kind": "call",
                                                    "id": "51007",
                                                    "channel": "call",
                                                    "title": "Call",
                                                    "url": "/app/calls/51007",
                                                    "call": {
                                                        "direction": "inbound",
                                                        "duration_seconds": 192,
                                                        "started_at": "2026-09-25T11:02:10+03:00",
                                                        "outcome": "answered",
                                                        "has_recording": true
                                                    },
                                                    "is_origin": false,
                                                    "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                    "last_seen_at": "2026-09-25T11:05:22+03:00"
                                                }
                                            ],
                                            "possible_duplicate": null
                                        },
                                        "refused": []
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/leads/{lead}/assign": {
            "post": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadAssign",
                "summary": "Give a lead to someone",
                "description": "Assign the lead to an active team member, or send `user_id: null` to put it back in the unassigned pool. The new owner is notified.",
                "x-permission": "leads.assign",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters. A repeat of a key whose call succeeded, within 24 hours, replays the first answer with `X-Idempotent-Replay: 1` and changes nothing. A refused call does not spend its key.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "crm-sync-2026-09-26-0042"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "user_id"
                                ],
                                "properties": {
                                    "user_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ],
                                        "description": "A team member id, or null for the pool."
                                    }
                                }
                            },
                            "example": {
                                "user_id": 311
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The lead with its new owner.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Lead",
                                            "description": "The lead with its new owner."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                        "name": "Amina Juma",
                                        "title": "Amina Juma",
                                        "company": "Amina Shop",
                                        "phone": "+255712345678",
                                        "email": null,
                                        "stage": "qualified",
                                        "stage_label": "Qualified",
                                        "closed": false,
                                        "archived": false,
                                        "labels": [
                                            {
                                                "id": 1,
                                                "name": "hot",
                                                "color": "#e11d48"
                                            }
                                        ],
                                        "interest": "Solar kit 5 kW",
                                        "estimated_value": 4500000,
                                        "currency": "TZS",
                                        "score": 72,
                                        "source_channel": "whatsapp",
                                        "assigned_to": {
                                            "id": 311,
                                            "name": "Baraka M."
                                        },
                                        "next_action": "Send quote",
                                        "next_action_at": "2026-09-26T10:00:00+03:00",
                                        "overdue": false,
                                        "created_by": {
                                            "kind": "ai",
                                            "id": 14
                                        },
                                        "last_activity_at": "2026-09-25T14:03:11+03:00",
                                        "created_at": "2026-09-24T09:12:40+03:00",
                                        "location": "Mbezi, Dar es Salaam",
                                        "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                        "score_reason": "Budget stated, wants install this month",
                                        "source_detail": "Ad: October solar promo",
                                        "source_meta": {
                                            "ad_id": "120210000000001",
                                            "ad_headline": "October solar promo"
                                        },
                                        "lost_reason": null,
                                        "custom_fields": {
                                            "budget_band": "mid"
                                        },
                                        "missing_fields": [],
                                        "stage_changed_at": "2026-09-25T14:03:11+03:00",
                                        "closed_at": null,
                                        "archived_at": null,
                                        "last_contacted_at": "2026-09-25T14:03:11+03:00",
                                        "identities": [
                                            {
                                                "kind": "whatsapp",
                                                "value": "255712345678"
                                            },
                                            {
                                                "kind": "phone",
                                                "value": "255712345678"
                                            }
                                        ],
                                        "sources": [
                                            {
                                                "kind": "conversation",
                                                "id": "88213",
                                                "channel": "whatsapp",
                                                "title": "WhatsApp chat",
                                                "url": "/app/communications/inbox?conversation=88213",
                                                "is_origin": true,
                                                "first_seen_at": "2026-09-24T09:12:40+03:00",
                                                "last_seen_at": "2026-09-25T14:03:11+03:00"
                                            },
                                            {
                                                "kind": "call",
                                                "id": "51007",
                                                "channel": "call",
                                                "title": "Call",
                                                "url": "/app/calls/51007",
                                                "call": {
                                                    "direction": "inbound",
                                                    "duration_seconds": 192,
                                                    "started_at": "2026-09-25T11:02:10+03:00",
                                                    "outcome": "answered",
                                                    "has_recording": true
                                                },
                                                "is_origin": false,
                                                "first_seen_at": "2026-09-25T11:05:22+03:00",
                                                "last_seen_at": "2026-09-25T11:05:22+03:00"
                                            }
                                        ],
                                        "possible_duplicate": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/leads/{lead}/notes": {
            "post": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadNoteAdd",
                "summary": "Write a note on a lead",
                "description": "Adds a note to the lead's timeline and sends `lead.note_added`.",
                "x-permission": "leads.edit",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters. A repeat of a key whose call succeeded, within 24 hours, replays the first answer with `X-Idempotent-Replay: 1` and changes nothing. A refused call does not spend its key.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "crm-sync-2026-09-26-0042"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "body"
                                ],
                                "properties": {
                                    "body": {
                                        "type": "string",
                                        "description": "The note.",
                                        "maxLength": 2000
                                    }
                                }
                            },
                            "example": {
                                "body": "Called her. Sending the quote Friday."
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The note as written.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/LeadActivity",
                                            "description": "The note as written."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 9002,
                                        "type": "note",
                                        "changes": null,
                                        "body": "Called her. Sending the quote Friday.",
                                        "redacted": false,
                                        "actor": {
                                            "kind": "api",
                                            "id": 7,
                                            "label": "API"
                                        },
                                        "source": null,
                                        "engine_run_id": null,
                                        "meta": null,
                                        "created_at": "2026-09-25T14:03:11+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/leads/{lead}/activities": {
            "get": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadActivities",
                "summary": "Read a lead's timeline",
                "description": "Everything that happened to the lead, newest first: created, field changes, stage moves, labels, notes, assignments, attached calls and chats \u2014 by people, the AI agent, API keys and flows. A lead that absorbed another in a merge shows both timelines. Page backwards with `before`.",
                "x-permission": "leads.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "lead",
                        "in": "path",
                        "required": true,
                        "description": "The lead's `id` \u2014 the uuid every lead response carries.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                    },
                    {
                        "name": "before",
                        "in": "query",
                        "required": false,
                        "description": "Only activities older than this id \u2014 pass `data.next_before` from the previous page.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "example": 9001
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "How many, 1\u2013100. Defaults to 50.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 50
                        },
                        "example": 50
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The timeline, newest first.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "Activities, newest first.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/LeadActivity"
                                                    }
                                                },
                                                "next_before": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "Pass as `before` to read further back; null when there is nothing older."
                                                }
                                            },
                                            "description": "The timeline, newest first."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 9001,
                                                "type": "stage_changed",
                                                "changes": {
                                                    "stage": {
                                                        "from": "contacted",
                                                        "to": "qualified"
                                                    }
                                                },
                                                "body": null,
                                                "redacted": false,
                                                "actor": {
                                                    "kind": "ai",
                                                    "id": 14,
                                                    "label": "Mauzo AI"
                                                },
                                                "source": {
                                                    "kind": "conversation",
                                                    "id": "88213",
                                                    "channel": "whatsapp",
                                                    "title": "WhatsApp chat",
                                                    "url": "/app/communications/inbox?conversation=88213"
                                                },
                                                "engine_run_id": 55120,
                                                "meta": null,
                                                "created_at": "2026-09-25T14:03:11+03:00"
                                            }
                                        ],
                                        "next_before": null
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/lead-labels": {
            "get": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadLabelList",
                "summary": "List lead labels",
                "description": "The workspace's labels, alphabetically, with how many leads carry each. The names are what `labels` takes on a lead.",
                "x-permission": "leads.view",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The labels.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/LeadLabel"
                                            },
                                            "description": "The labels."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": [
                                        {
                                            "id": 12,
                                            "name": "callback-requested",
                                            "color": "#7c3aed",
                                            "description": "Asked us to call them back.",
                                            "ai_assignable": true,
                                            "created_by_kind": "system",
                                            "leads_count": 18,
                                            "created_at": "2026-09-24T09:12:40+03:00",
                                            "updated_at": "2026-09-24T09:12:40+03:00"
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "post": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadLabelCreate",
                "summary": "Create a lead label",
                "description": "Adds a label the whole workspace \u2014 people and the AI agent \u2014 can use.",
                "x-permission": "leads.settings",
                "x-permission-scope": "controller",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "The name, unique in the workspace regardless of case.",
                                        "maxLength": 64
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "Hex colour, #rrggbb. Defaults to blue.",
                                        "pattern": "^#[0-9A-Fa-f]{6}$"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "When to use it \u2014 the AI agent reads this.",
                                        "maxLength": 255
                                    },
                                    "ai_assignable": {
                                        "type": "boolean",
                                        "description": "Whether the AI agent may use it. Defaults to true."
                                    }
                                },
                                "required": [
                                    "name"
                                ]
                            },
                            "example": {
                                "name": "callback-requested",
                                "color": "#7c3aed",
                                "description": "Asked us to call them back."
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The label.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/LeadLabel",
                                            "description": "The label."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 12,
                                        "name": "callback-requested",
                                        "color": "#7c3aed",
                                        "description": "Asked us to call them back.",
                                        "ai_assignable": true,
                                        "created_by_kind": "system",
                                        "leads_count": 18,
                                        "created_at": "2026-09-24T09:12:40+03:00",
                                        "updated_at": "2026-09-24T09:12:40+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/lead-labels/{label}": {
            "patch": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadLabelUpdate",
                "summary": "Change a lead label",
                "description": "Rename it, recolour it, reword its description or keep it away from the AI agent. Every lead carrying it follows.",
                "x-permission": "leads.settings",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "label",
                        "in": "path",
                        "required": true,
                        "description": "The label's numeric `id` from `GET /api/v3/lead-labels`.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 12
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "description": "The name, unique in the workspace regardless of case.",
                                        "maxLength": 64
                                    },
                                    "color": {
                                        "type": "string",
                                        "description": "Hex colour, #rrggbb. Defaults to blue.",
                                        "pattern": "^#[0-9A-Fa-f]{6}$"
                                    },
                                    "description": {
                                        "type": "string",
                                        "description": "When to use it \u2014 the AI agent reads this.",
                                        "maxLength": 255
                                    },
                                    "ai_assignable": {
                                        "type": "boolean",
                                        "description": "Whether the AI agent may use it. Defaults to true."
                                    }
                                }
                            },
                            "example": {
                                "ai_assignable": false
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The label as it is now.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/LeadLabel",
                                            "description": "The label as it is now."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 12,
                                        "name": "callback-requested",
                                        "color": "#7c3aed",
                                        "description": "Asked us to call them back.",
                                        "ai_assignable": true,
                                        "created_by_kind": "system",
                                        "leads_count": 18,
                                        "created_at": "2026-09-24T09:12:40+03:00",
                                        "updated_at": "2026-09-24T09:12:40+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            },
            "delete": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadLabelDelete",
                "summary": "Delete a lead label",
                "description": "The label comes off every lead that carried it.",
                "x-permission": "leads.settings",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "label",
                        "in": "path",
                        "required": true,
                        "description": "The label's numeric `id` from `GET /api/v3/lead-labels`.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 12
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The label was deleted.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "id": {
                                                    "type": "integer",
                                                    "description": "The deleted label's id."
                                                },
                                                "deleted": {
                                                    "type": "boolean",
                                                    "description": "Always true."
                                                }
                                            },
                                            "description": "The label was deleted."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 12,
                                        "deleted": true
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/lead-fields": {
            "get": {
                "tags": [
                    "Leads"
                ],
                "operationId": "v3LeadFieldList",
                "summary": "List custom lead fields",
                "description": "The custom fields the workspace defined for its leads \u2014 what a lead's `custom_fields` may carry. Fields are defined in the dashboard.",
                "x-permission": "leads.view",
                "x-permission-scope": "controller",
                "responses": {
                    "200": {
                        "description": "The fields, in display order.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/LeadField"
                                            },
                                            "description": "The fields, in display order."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": [
                                        {
                                            "key": "budget_band",
                                            "label": "Budget band",
                                            "type": "select",
                                            "options": [
                                                {
                                                    "key": "low",
                                                    "label": "< 1M"
                                                },
                                                {
                                                    "key": "mid",
                                                    "label": "1\u20135M"
                                                },
                                                {
                                                    "key": "high",
                                                    "label": "> 5M"
                                                }
                                            ],
                                            "required": false,
                                            "ai_writable": true,
                                            "ai_hint": "The budget the customer mentioned",
                                            "position": 1
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/webhooks/{webhook}/test": {
            "post": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "v3WebhookTest",
                "summary": "Send a test event",
                "description": "Sends one event to this receiver now and tells you what it answered \u2014 the quickest way to check a URL, a signature check or a custom header before real events flow. The body is the catalogue sample of the event you name (`webhook.test` by default), marked `\"test\": true`, signed exactly like a real delivery. The attempt is recorded in the delivery log but never retried.",
                "x-permission": "webhooks.manage",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "webhook",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        },
                        "description": "Webhook id.",
                        "example": 7
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "properties": {
                                    "event": {
                                        "type": "string",
                                        "description": "Which sample to send: any name from `GET /api/v3/webhooks/events`. Defaults to webhook.test."
                                    }
                                }
                            },
                            "example": {
                                "event": "lead.stage_changed"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "What the receiver answered.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "properties": {
                                                "delivered": {
                                                    "type": "boolean",
                                                    "description": "True when the receiver answered 2xx."
                                                },
                                                "status": {
                                                    "type": [
                                                        "integer",
                                                        "null"
                                                    ],
                                                    "description": "The HTTP status it answered; null when nothing answered."
                                                },
                                                "duration_ms": {
                                                    "type": "integer",
                                                    "description": "How long the attempt took."
                                                },
                                                "response_excerpt": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "The start of its response body."
                                                },
                                                "error": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Why nothing usable came back: a timeout, a refused connection, a blocked address."
                                                },
                                                "delivery_id": {
                                                    "type": "string",
                                                    "description": "The delivery record, as it appears in the delivery log."
                                                }
                                            },
                                            "description": "What the receiver answered."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "delivered": true,
                                        "status": 200,
                                        "duration_ms": 184,
                                        "response_excerpt": "{\"received\":true}",
                                        "error": null,
                                        "delivery_id": "dlv_01j9qk3v8x2m7n4p5r6s"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/{form}/deployments": {
            "post": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormDeploy",
                "summary": "Put a form on more WhatsApp accounts",
                "description": "WhatsApp will not send a form from a number on another account than the one it was made on. This adds accounts: a live form is published on each at once (its own copy), and every later publish reaches them too. A chat is always sent the copy for the number it is on. One account WhatsApp refuses does not stop the others \u2014 read `live_status` and `error` per account.",
                "x-permission": "forms.publish",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "waba_ids"
                                ],
                                "properties": {
                                    "waba_ids": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "minItems": 1,
                                        "maxItems": 20,
                                        "description": "The WhatsApp business account ids to add. `GET /api/v3/whatsapp/accounts` lists them; the form's home account is ignored."
                                    }
                                }
                            },
                            "example": {
                                "waba_ids": [
                                    "209900112233445"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Added; each account's state is in `accounts`.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The form and its accounts now.",
                                            "properties": {
                                                "form_id": {
                                                    "type": "string",
                                                    "format": "uuid",
                                                    "description": "The form's uuid."
                                                },
                                                "accounts": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppFormAccount"
                                                    },
                                                    "description": "Every WhatsApp account, with the form's state on each."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "form_id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                        "accounts": [
                                            {
                                                "waba_id": "102290129340398",
                                                "name": "Afya Bora",
                                                "numbers": [
                                                    "+255 712 400 118"
                                                ],
                                                "role": "home",
                                                "live_status": "PUBLISHED",
                                                "sendable": true,
                                                "error": null,
                                                "published_at": "2026-09-26T09:14:02+00:00"
                                            },
                                            {
                                                "waba_id": "209900112233445",
                                                "name": "Duka la Pili",
                                                "numbers": [
                                                    "+255 754 900 111"
                                                ],
                                                "role": "added",
                                                "live_status": "PUBLISHED",
                                                "sendable": true,
                                                "error": null,
                                                "published_at": "2026-09-26T10:02:40+00:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/whatsapp/forms/{form}/deployments/{waba}": {
            "delete": {
                "tags": [
                    "WhatsApp forms"
                ],
                "operationId": "v3WhatsAppFormUndeploy",
                "summary": "Take a form off a WhatsApp account",
                "description": "Removes one of the form's added accounts. Its copies there are retired at WhatsApp; a form a customer already opened still answers. The home account cannot be removed (422).",
                "x-permission": "forms.publish",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "form",
                        "in": "path",
                        "required": true,
                        "description": "The form's uuid.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10"
                    },
                    {
                        "name": "waba",
                        "in": "path",
                        "required": true,
                        "description": "The WhatsApp business account id to take the form off.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "209900112233445"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Removed; the accounts now.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The form and its accounts now.",
                                            "properties": {
                                                "form_id": {
                                                    "type": "string",
                                                    "format": "uuid",
                                                    "description": "The form's uuid."
                                                },
                                                "accounts": {
                                                    "type": "array",
                                                    "items": {
                                                        "$ref": "#/components/schemas/WhatsAppFormAccount"
                                                    },
                                                    "description": "Every WhatsApp account, with the form's state on each."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "form_id": "4f2c7b1e-8d3a-4f6b-9c21-7a5e0d9b3c10",
                                        "accounts": [
                                            {
                                                "waba_id": "102290129340398",
                                                "name": "Afya Bora",
                                                "numbers": [
                                                    "+255 712 400 118"
                                                ],
                                                "role": "home",
                                                "live_status": "PUBLISHED",
                                                "sendable": true,
                                                "error": null,
                                                "published_at": "2026-09-26T09:14:02+00:00"
                                            },
                                            {
                                                "waba_id": "209900112233445",
                                                "name": "Duka la Pili",
                                                "numbers": [
                                                    "+255 754 900 111"
                                                ],
                                                "role": "added",
                                                "live_status": "PUBLISHED",
                                                "sendable": true,
                                                "error": null,
                                                "published_at": "2026-09-26T10:02:40+00:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/voice/otp": {
            "post": {
                "tags": [
                    "Voice"
                ],
                "operationId": "v3VoiceOtpSend",
                "summary": "Call a number and say a code",
                "description": "Rings `to` and says the code from a voice pack: \"Msimbo wako ni \u2014 nne, nane, moja, saba. Narudia: \u2026 Bonyeza moja kusikia tena.\" The digits are pre-recorded clips joined on the PBX with fixed gaps (the last digit has a falling tone), so there is no text-to-speech per call and the only charge is the call minute. Pressing 1 says it again. The call is never recorded or transcribed, the digits are kept out of call events, and Momo stores only a hash of the code. Send `code`, or `generate: {length}` to have Momo make one \u2014 it is returned in this response only. Each number gets at most 3 codes in 10 minutes; only listed countries are rung. Answers 202: follow the call through `voice.otp.answered|completed|failed` webhooks or `GET /api/v3/voice/otp/{uid}`. Needs `calls.place` on the key's issuer. A code is the person's own request, so neither the do-not-call list nor calling hours stop it; the per-number limit (3 in 10 minutes) does.",
                "x-permission": "calls.place",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters, unique per intended call. A repeat with the same key replays the first answer (`X-Idempotent-Replay: 1` within 24 hours; the same `uid` after that) and never rings twice. The PBX call carries a key derived from it.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "login-55102-otp-1"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "to"
                                ],
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "description": "The number to ring. International form (`+255712345678`); a Tanzanian `0712\u2026` or `712\u2026` is read as +255. Only listed countries are allowed (Tanzania by default)."
                                    },
                                    "code": {
                                        "type": "string",
                                        "pattern": "^[0-9]{4,10}$",
                                        "description": "The code to say, 4-10 digits. Required unless `generate` is sent."
                                    },
                                    "generate": {
                                        "type": "object",
                                        "description": "Have Momo make the code instead; it comes back once as `data.code`.",
                                        "properties": {
                                            "length": {
                                                "type": "integer",
                                                "minimum": 4,
                                                "maximum": 10,
                                                "default": 6,
                                                "description": "How many digits."
                                            }
                                        }
                                    },
                                    "language": {
                                        "type": "string",
                                        "enum": [
                                            "sw",
                                            "en"
                                        ],
                                        "default": "sw",
                                        "description": "Kiswahili (`sw`) or English (`en`)."
                                    },
                                    "voice_pack": {
                                        "type": "string",
                                        "description": "A voice pack slug: a platform pack (`sw-rehema-digits`, `en-daudi-digits`) or one your workspace built in Asset Studio. Default: the platform pack for `language`."
                                    },
                                    "repeat": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 3,
                                        "default": 2,
                                        "description": "How many times the code is said in one go (\"Narudia\" between them)."
                                    },
                                    "external_ref": {
                                        "type": "string",
                                        "maxLength": 128,
                                        "description": "Your own reference, echoed on the status and every webhook."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "One of your workspace's numbers to call from. Default: the first one."
                                    }
                                }
                            },
                            "examples": {
                                "code": {
                                    "summary": "Your code",
                                    "value": {
                                        "to": "+255712345678",
                                        "code": "4817",
                                        "language": "sw",
                                        "voice_pack": "sw-rehema-digits",
                                        "repeat": 2,
                                        "external_ref": "login-55102"
                                    }
                                },
                                "generate": {
                                    "summary": "Momo makes the code",
                                    "value": {
                                        "to": "+255712345678",
                                        "generate": {
                                            "length": 6
                                        },
                                        "language": "en"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Queued: the phone rings within seconds.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "uid",
                                                "status",
                                                "expires_at"
                                            ],
                                            "description": "The code call.",
                                            "properties": {
                                                "uid": {
                                                    "type": "string",
                                                    "description": "The code call's id (`vc_\u2026`)."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`queued`, or already `calling`."
                                                },
                                                "expires_at": {
                                                    "type": "string",
                                                    "format": "date-time",
                                                    "description": "After this the call is not placed. Use the same window when you check the code."
                                                },
                                                "code": {
                                                    "type": "string",
                                                    "description": "Only when you sent `generate`: the code Momo made. It is not stored and not shown again."
                                                }
                                            }
                                        }
                                    }
                                },
                                "examples": {
                                    "queued": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "uid": "vc_01J9ZB5Q4M3T8W5K2N7ABCDEF0",
                                                "status": "queued",
                                                "expires_at": "2026-10-07T14:10:00+03:00"
                                            }
                                        }
                                    },
                                    "generated": {
                                        "value": {
                                            "status": "success",
                                            "data": {
                                                "uid": "vc_01J9ZB5Q4M3T8W5K2N7ABCDEF2",
                                                "status": "queued",
                                                "expires_at": "2026-10-07T14:10:00+03:00",
                                                "code": "305917"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "402": {
                        "description": "The wallet cannot pay for one answered call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VoiceRefusalEnvelope"
                                },
                                "examples": {
                                    "noMoney": {
                                        "value": {
                                            "status": "error",
                                            "message": "The wallet cannot pay for this call. Top up and try again.",
                                            "code": "insufficient_balance",
                                            "details": {
                                                "required": 87,
                                                "available": 40,
                                                "currency": "TZS"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "Refused. See `code`; a malformed body is the usual `errors` envelope instead.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VoiceRefusalEnvelope"
                                },
                                "examples": {
                                    "country": {
                                        "value": {
                                            "status": "error",
                                            "message": "Voice calls can only be placed to numbers in: +255.",
                                            "code": "country_not_allowed",
                                            "details": {
                                                "allowed_country_codes": [
                                                    "255"
                                                ]
                                            }
                                        }
                                    },
                                    "pack": {
                                        "value": {
                                            "status": "error",
                                            "message": "The voice pack \"sw-rehema-digits\" is missing clips and cannot say codes yet.",
                                            "code": "voice_pack_not_ready"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many codes for this number (3 in 10 minutes), or the key's own send limit. Wait for Retry-After.",
                        "headers": {
                            "Retry-After": {
                                "description": "Seconds to wait.",
                                "schema": {
                                    "type": "integer"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VoiceRefusalEnvelope"
                                },
                                "examples": {
                                    "perNumber": {
                                        "value": {
                                            "status": "error",
                                            "message": "This number has had 3 codes in the last 10 minutes. Try again later.",
                                            "code": "rate_limited",
                                            "details": {
                                                "retry_after": 412
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api/v3/voice/otp/{uid}": {
            "get": {
                "tags": [
                    "Voice"
                ],
                "operationId": "v3VoiceOtpShow",
                "summary": "Read a voice code call",
                "description": "Where the code call got to: status, outcome, keys pressed, timings. The code is never returned, only its length. Needs `calls.view` on the key's issuer.",
                "x-permission": "calls.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The `uid` from `POST /api/v3/voice/otp`.",
                        "schema": {
                            "type": "string",
                            "pattern": "^vc_[0-9A-Za-z]+$"
                        },
                        "example": "vc_01J9ZB5Q4M3T8W5K2N7ABCDEF0"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The code call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/VoiceOtp",
                                            "description": "The code call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "uid": "vc_01J9ZB5Q4M3T8W5K2N7ABCDEF0",
                                        "type": "otp",
                                        "status": "completed",
                                        "to": "+255712345678",
                                        "language": "sw",
                                        "repeat": 2,
                                        "external_ref": "login-55102",
                                        "outcome": "answered",
                                        "failure_reason": null,
                                        "keys_pressed": [
                                            {
                                                "digit": "1",
                                                "action": "repeat",
                                                "at": "2026-10-07T14:00:19+03:00",
                                                "event_id": "evt-81aa"
                                            }
                                        ],
                                        "talk_seconds": 21,
                                        "estimated_cost": 87,
                                        "created_at": "2026-10-07T14:00:00+03:00",
                                        "placed_at": "2026-10-07T14:00:00+03:00",
                                        "answered_at": "2026-10-07T14:00:09+03:00",
                                        "completed_at": "2026-10-07T14:00:30+03:00",
                                        "failed_at": null,
                                        "code_length": 4,
                                        "voice_pack": "sw-rehema-digits",
                                        "expires_at": "2026-10-07T14:10:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/voice/messages": {
            "post": {
                "tags": [
                    "Voice"
                ],
                "operationId": "v3VoiceMessageSend",
                "summary": "Call a number and speak a message",
                "description": "Rings `to` and speaks `message.text` in the chosen voice, then listens for the keys you set. The audio is generated the first time these exact words are used in this voice and kept: that first time is charged per character at the voice model's rate, every later call with the same words and voice costs nothing extra (`tts.cached`). The call itself is the ordinary outbound minute. `voice_id` takes a voice name (`Kore`, `sw-KE-Chirp3-HD-Aoede`), a catalogue id, or a voice pack persona (`rehema` \u2014 the voice of the Kiswahili code pack); leave it out for the default voice. Keys: `repeat`, `end` and `agent` act on the call; `confirm`, `decline`, `cancel`, `callback`, `opt_out` and `report` are reported back for you to act on (`keys_pressed` on `voice.message.completed`). Answers 202. Needs `calls.place` on the key's issuer. Like every business call it keeps the do-not-call list and the workspace calling hours (Mon\u2013Sat 08:00\u201320:00 by default), and one number gets at most 5 messages an hour (configurable).",
                "x-permission": "calls.place",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any string up to 255 characters, unique per intended call. A repeat with the same key replays the first answer (`X-Idempotent-Replay: 1` within 24 hours; the same `uid` after that) and never rings twice. The PBX call carries a key derived from it.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "order-A1023-confirm"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "to",
                                    "message"
                                ],
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "description": "The number to ring. International form (`+255712345678`); a Tanzanian `0712\u2026` or `712\u2026` is read as +255. Only listed countries are allowed (Tanzania by default)."
                                    },
                                    "message": {
                                        "type": "object",
                                        "required": [
                                            "text"
                                        ],
                                        "description": "What to say.",
                                        "properties": {
                                            "text": {
                                                "type": "string",
                                                "minLength": 2,
                                                "maxLength": 1000,
                                                "description": "The words, up to 1,000 characters. Say who is calling first; personal details make every message a new (charged) generation."
                                            }
                                        }
                                    },
                                    "voice_id": {
                                        "type": "string",
                                        "description": "The voice: a name (`Kore`, `sw-KE-Chirp3-HD-Aoede`), a catalogue voice id, or a voice pack persona (`rehema`, `daudi`). Default: the platform's default speech voice."
                                    },
                                    "model_id": {
                                        "type": "string",
                                        "description": "The speech model, by id or name (`gemini-2.5-flash-preview-tts`, `google-chirp3-hd`). Usually implied by the voice."
                                    },
                                    "language": {
                                        "type": "string",
                                        "enum": [
                                            "sw",
                                            "en"
                                        ],
                                        "default": "sw",
                                        "description": "Kiswahili (`sw`) or English (`en`)."
                                    },
                                    "keys": {
                                        "type": "object",
                                        "description": "Phone keys \u2192 action: `{\"1\": \"confirm\", \"2\": \"agent\"}`, or `{\"1\": {\"action\": \"confirm\", \"label\": \"Yes\"}}`. Actions: repeat, end, agent, confirm, decline, cancel, callback, opt_out, report.",
                                        "additionalProperties": {
                                            "description": "An action word, or `{action, label}`."
                                        }
                                    },
                                    "repeat": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 3,
                                        "default": 1,
                                        "description": "How many times the message plays."
                                    },
                                    "external_ref": {
                                        "type": "string",
                                        "maxLength": 128,
                                        "description": "Your own reference, echoed on the status and every webhook."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "One of your workspace's numbers to call from. Default: the first one."
                                    }
                                }
                            },
                            "example": {
                                "to": "+255712345678",
                                "message": {
                                    "text": "Habari Amina, oda yako A1023 imefika. Bonyeza 1 kuthibitisha."
                                },
                                "voice_id": "rehema",
                                "model_id": "google-chirp3-hd",
                                "keys": {
                                    "1": "confirm",
                                    "2": "agent"
                                },
                                "repeat": 1
                            }
                        }
                    }
                },
                "responses": {
                    "202": {
                        "description": "Queued: the audio is prepared (or found) and the phone rings.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "uid",
                                                "status",
                                                "estimated_cost"
                                            ],
                                            "description": "The message call.",
                                            "properties": {
                                                "uid": {
                                                    "type": "string",
                                                    "description": "The message call's id (`vm_\u2026`)."
                                                },
                                                "status": {
                                                    "type": "string",
                                                    "description": "`queued`, or already `calling`."
                                                },
                                                "estimated_cost": {
                                                    "type": "number",
                                                    "description": "One answered call (minute and connect fee) plus the speech if it is not cached yet, in the wallet currency."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "uid": "vm_01J9ZB5Q4M3T8W5K2N7ABCDEF1",
                                        "status": "queued",
                                        "estimated_cost": 87
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "402": {
                        "description": "The wallet cannot pay for one answered call and the speech.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VoiceRefusalEnvelope"
                                },
                                "examples": {
                                    "noMoney": {
                                        "value": {
                                            "status": "error",
                                            "message": "The wallet cannot pay for this call. Top up and try again.",
                                            "code": "insufficient_balance",
                                            "details": {
                                                "required": 88.71,
                                                "available": 40,
                                                "currency": "TZS"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "422": {
                        "description": "Refused. See `code`; a malformed body is the usual `errors` envelope instead.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/VoiceRefusalEnvelope"
                                },
                                "examples": {
                                    "voice": {
                                        "value": {
                                            "status": "error",
                                            "message": "No speech voice matches voice_id \"nobody\". Leave both out for the default voice.",
                                            "code": "unknown_voice"
                                        }
                                    },
                                    "keys": {
                                        "value": {
                                            "status": "error",
                                            "message": "Key 1 has an unknown action \"dance\". Use one of: repeat, end, agent, confirm, decline, cancel, callback, opt_out, report.",
                                            "code": "invalid_keys"
                                        }
                                    },
                                    "optedOut": {
                                        "summary": "On the do-not-call list",
                                        "value": {
                                            "status": "error",
                                            "message": "This person asked not to be called (they are on the do-not-call list).",
                                            "code": "opted_out"
                                        }
                                    },
                                    "outsideHours": {
                                        "summary": "Outside calling hours",
                                        "value": {
                                            "status": "error",
                                            "message": "Calls only go out inside calling hours (08:00\u201320:00 Mon\u2013Sat).",
                                            "code": "outside_calling_hours",
                                            "details": {
                                                "next_opening": "2026-10-08T08:00:00+03:00"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/voice/messages/{uid}": {
            "get": {
                "tags": [
                    "Voice"
                ],
                "operationId": "v3VoiceMessageShow",
                "summary": "Read a voice message call",
                "description": "Where the message call got to: status, outcome, keys pressed, timings, and what its speech cost. Needs `calls.view` on the key's issuer.",
                "x-permission": "calls.view",
                "x-permission-scope": "controller",
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The `uid` from `POST /api/v3/voice/messages`.",
                        "schema": {
                            "type": "string",
                            "pattern": "^vm_[0-9A-Za-z]+$"
                        },
                        "example": "vm_01J9ZB5Q4M3T8W5K2N7ABCDEF1"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The message call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/VoiceMessage",
                                            "description": "The message call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "uid": "vm_01J9ZB5Q4M3T8W5K2N7ABCDEF1",
                                        "type": "message",
                                        "status": "completed",
                                        "to": "+255712345678",
                                        "language": "sw",
                                        "repeat": 1,
                                        "external_ref": "order-A1023",
                                        "outcome": "answered",
                                        "failure_reason": null,
                                        "keys_pressed": [
                                            {
                                                "digit": "1",
                                                "action": "confirm",
                                                "at": "2026-10-07T14:00:15+03:00",
                                                "event_id": "evt-81ab"
                                            }
                                        ],
                                        "talk_seconds": 14,
                                        "estimated_cost": 88.71,
                                        "created_at": "2026-10-07T14:00:00+03:00",
                                        "placed_at": "2026-10-07T14:00:00+03:00",
                                        "answered_at": "2026-10-07T14:00:08+03:00",
                                        "completed_at": "2026-10-07T14:00:22+03:00",
                                        "failed_at": null,
                                        "text": "Habari Amina, oda yako A1023 imefika. Bonyeza 1 kuthibitisha.",
                                        "voice_id": "sw-KE-Chirp3-HD-Aoede",
                                        "model_id": "cloud-tts-chirp3-hd",
                                        "keys": {
                                            "1": {
                                                "action": "confirm"
                                            },
                                            "2": {
                                                "action": "agent"
                                            }
                                        },
                                        "tts": {
                                            "characters": 62,
                                            "cached": false,
                                            "cost": 1.71
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                }
            }
        },
        "/api/v3/calls": {
            "post": {
                "tags": [
                    "Calls"
                ],
                "operationId": "v3CallPlace",
                "summary": "Place one call now",
                "description": "Rings `to` now with a message (and keys), an AI agent or an IVR flow \u2014 for example, to confirm a cash-on-delivery order. The call is built exactly as a campaign person's call is. Refused before anything rings when the number is invalid, the person is on the do-not-call list, the number already had 5 API calls in the last hour (429 `rate_limited`, configurable), it is outside calling hours (Mon\u2013Sat 08:00\u201320:00 by default), or the wallet cannot pay for one answered call. Answers 201 with the call (ringing); the result comes as `call.completed` (keys pressed included) or GET /api/v3/calls/{id}. Needs `calls.place` on the key's issuer.",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any unique string per intended action. A retry with the same key replays the first answer (24 h) instead of acting twice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "cod-A1023-confirm"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "One call, described with the campaign composer's own fields.",
                                "properties": {
                                    "to": {
                                        "type": "string",
                                        "description": "The number to ring, international (+255\u2026) or local (07\u2026)."
                                    },
                                    "mode": {
                                        "type": "string",
                                        "description": "message, ai or ivr. Default: ai when an agent is named, else message.",
                                        "enum": [
                                            "message",
                                            "ai",
                                            "ivr"
                                        ]
                                    },
                                    "message": {
                                        "type": "object",
                                        "description": "message mode: what the person hears.",
                                        "properties": {
                                            "text": {
                                                "type": "string",
                                                "description": "The message (\u2264 2000); {placeholders} filled from `variables`."
                                            },
                                            "audio_asset_id": {
                                                "type": "integer",
                                                "description": "A published recording to play instead."
                                            },
                                            "voice_id": {
                                                "type": "string",
                                                "description": "The voice."
                                            },
                                            "voice_model": {
                                                "type": "string",
                                                "description": "The speech model."
                                            },
                                            "language": {
                                                "type": "string",
                                                "description": "sw or en."
                                            },
                                            "repeat": {
                                                "type": "integer",
                                                "description": "Plays (1-3) when no key is pressed."
                                            }
                                        }
                                    },
                                    "keys": {
                                        "type": "object",
                                        "description": "Digit \u2192 what pressing it does (as on a campaign). Every key is reported back on `call.completed`; 9 is always \"stop calling me\".",
                                        "additionalProperties": {
                                            "type": "object",
                                            "description": "What pressing this digit does.",
                                            "properties": {
                                                "action": {
                                                    "type": "string",
                                                    "description": "confirm, ring_group, sms, tag, add_to_group, callback, repeat, agent, start_flow or opt_out. Live actions (repeat, ring_group, agent) happen on the call; the others happen in Momo after the key is reported.",
                                                    "enum": [
                                                        "confirm",
                                                        "ring_group",
                                                        "sms",
                                                        "tag",
                                                        "add_to_group",
                                                        "callback",
                                                        "repeat",
                                                        "agent",
                                                        "start_flow",
                                                        "opt_out"
                                                    ]
                                                },
                                                "label": {
                                                    "type": "string",
                                                    "description": "What the key means, in the business's words (\u2264 120 characters). Echoed on keys_pressed."
                                                },
                                                "say": {
                                                    "type": "string",
                                                    "description": "What the call says before acting on the key, e.g. \"Asante, tumepokea.\""
                                                },
                                                "ring_group_id": {
                                                    "type": "integer",
                                                    "description": "ring_group: the group to ring."
                                                },
                                                "agent_config_id": {
                                                    "type": "string",
                                                    "description": "agent: the AI agent to hand the person to (default: the campaign's)."
                                                },
                                                "text": {
                                                    "type": "string",
                                                    "description": "sms: the SMS sent to the person; {placeholders} are filled from their details."
                                                },
                                                "sender_id": {
                                                    "type": "string",
                                                    "description": "sms: the sender to send it from (default: the workspace's)."
                                                },
                                                "tag": {
                                                    "type": "string",
                                                    "description": "tag: the tag put on the person and their contact."
                                                },
                                                "contact_group_id": {
                                                    "type": "integer",
                                                    "description": "add_to_group: the contact group to add them to."
                                                },
                                                "group_name": {
                                                    "type": "string",
                                                    "description": "add_to_group: a group to create (or reuse) by name instead."
                                                },
                                                "flow_id": {
                                                    "type": "integer",
                                                    "description": "start_flow: the live WhatsApp flow started in the person's WhatsApp thread."
                                                },
                                                "answer": {
                                                    "type": "object",
                                                    "description": "Also record an answer on the person, e.g. {\"key\": \"interested\", \"value\": true}.",
                                                    "properties": {
                                                        "key": {
                                                            "type": "string",
                                                            "description": "The answer key."
                                                        },
                                                        "value": {
                                                            "description": "The answer value."
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "ivr_flow_id": {
                                        "type": "integer",
                                        "description": "ivr mode: a published IVR flow."
                                    },
                                    "agent_config_id": {
                                        "type": "string",
                                        "description": "ai mode: the AI agent config id."
                                    },
                                    "agent_id": {
                                        "type": "integer",
                                        "description": "ai mode: the agent's id in Agents & AI, instead of agent_config_id."
                                    },
                                    "variables": {
                                        "type": "object",
                                        "description": "The person's details for the message and the agent.",
                                        "additionalProperties": {
                                            "type": "string",
                                            "description": "A detail value."
                                        }
                                    },
                                    "purpose": {
                                        "type": "string",
                                        "description": "ai mode: why we are calling (\u2264 500), for the agent."
                                    },
                                    "from": {
                                        "type": "string",
                                        "description": "One of the workspace's numbers to call from (default its first) \u2014 one the key's issuer may call from: someone whose calls are scoped to their own numbers gets only those."
                                    },
                                    "record": {
                                        "type": "boolean",
                                        "description": "Record the call (default: AI calls only)."
                                    },
                                    "max_call_seconds": {
                                        "type": "integer",
                                        "description": "The longest the call may last (30-1800)."
                                    },
                                    "ring_seconds": {
                                        "type": "integer",
                                        "description": "How long it rings (15-60)."
                                    },
                                    "external_ref": {
                                        "type": "string",
                                        "description": "Your own reference (\u2264 128), echoed on the call and its webhooks."
                                    }
                                },
                                "required": [
                                    "to"
                                ]
                            },
                            "example": {
                                "to": "+255712345678",
                                "mode": "message",
                                "message": {
                                    "text": "Habari {jina}, oda yako {oda} imefika. Bonyeza 1 kuthibitisha, 2 kuighairi."
                                },
                                "keys": {
                                    "1": {
                                        "action": "confirm",
                                        "label": "Thibitisha"
                                    },
                                    "2": {
                                        "action": "tag",
                                        "label": "Ghairi",
                                        "tag": "cancelled"
                                    }
                                },
                                "variables": {
                                    "jina": "Amina",
                                    "oda": "A1023"
                                },
                                "external_ref": "order-A1023"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "The call, ringing. A replay with the same Idempotency-Key answers 200 with the same call and rings nobody.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Call",
                                            "description": "The call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 81234,
                                        "room_name": "out-7f3c2a",
                                        "direction": "outbound",
                                        "status": "ringing",
                                        "outcome": null,
                                        "answered": false,
                                        "from": "+255746000111",
                                        "to": "+255712345678",
                                        "mode": "message",
                                        "agent_config_id": null,
                                        "source": "api",
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "answered_at": null,
                                        "ended_at": null,
                                        "duration_seconds": 0,
                                        "sip_status_code": null,
                                        "keys_pressed": [],
                                        "recording_available": false,
                                        "transcript_available": false,
                                        "request": {
                                            "external_ref": "order-A1023",
                                            "purpose": null,
                                            "variables": {
                                                "jina": "Amina",
                                                "oda": "A1023"
                                            },
                                            "estimated_cost": 87
                                        },
                                        "campaign": null
                                    }
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "The wallet cannot pay for one answered call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The wallet cannot pay for this call. Top up and try again.",
                                    "code": "insufficient_balance",
                                    "details": {
                                        "required": 87,
                                        "available": 10,
                                        "currency": "TZS"
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Refused (see `code`), or the body failed validation (`errors`, keyed by field).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "oneOf": [
                                        {
                                            "$ref": "#/components/schemas/CallRefusalEnvelope"
                                        },
                                        {
                                            "$ref": "#/components/schemas/LegacyErrorEnvelope"
                                        }
                                    ]
                                },
                                "examples": {
                                    "validation": {
                                        "summary": "Validation failed",
                                        "value": {
                                            "status": "error",
                                            "message": "Validation failed.",
                                            "errors": {
                                                "message.text": [
                                                    "Write the message people will hear, or choose a recording."
                                                ]
                                            }
                                        }
                                    },
                                    "outsideHours": {
                                        "summary": "Outside calling hours",
                                        "value": {
                                            "status": "error",
                                            "message": "Calls only go out inside calling hours (Mon\u2013Sat 08:00\u201320:00).",
                                            "code": "outside_calling_hours",
                                            "details": {
                                                "next_opening": "2026-10-08T08:00:00+03:00"
                                            }
                                        }
                                    },
                                    "optedOut": {
                                        "summary": "On the do-not-call list",
                                        "value": {
                                            "status": "error",
                                            "message": "This person asked not to be called (they are on the do-not-call list).",
                                            "code": "opted_out"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The phone system could not be reached; retry with the same Idempotency-Key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The phone system could not be reached. Retry with the same Idempotency-Key; it will not ring twice.",
                                    "code": "pbx_unreachable"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "calls.place",
                "x-permission-scope": "controller"
            },
            "get": {
                "tags": [
                    "Calls"
                ],
                "operationId": "v3CallList",
                "summary": "List calls",
                "description": "The workspace's calls, newest first, a page at a time. The key sees what its issuer sees on Call History (someone without org-wide calls scope sees their own calls). Needs `calls.history.view`.",
                "parameters": [
                    {
                        "name": "direction",
                        "in": "query",
                        "required": false,
                        "description": "inbound, outbound or internal.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "inbound",
                                "outbound",
                                "internal"
                            ]
                        },
                        "example": "outbound"
                    },
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Only calls in this status (ended, missed, ringing \u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "ended"
                    },
                    {
                        "name": "outcome",
                        "in": "query",
                        "required": false,
                        "description": "Only calls with this outcome (answered, no_answer, busy \u2026).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "answered"
                    },
                    {
                        "name": "number",
                        "in": "query",
                        "required": false,
                        "description": "Calls from or to this number (matched on the last 9 digits).",
                        "schema": {
                            "type": "string"
                        },
                        "example": "0712345678"
                    },
                    {
                        "name": "campaign_id",
                        "in": "query",
                        "required": false,
                        "description": "Only this campaign's calls.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    },
                    {
                        "name": "external_ref",
                        "in": "query",
                        "required": false,
                        "description": "Only calls placed by POST /api/v3/calls with this reference.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "order-A1023"
                    },
                    {
                        "name": "source",
                        "in": "query",
                        "required": false,
                        "description": "api, app or mcp (placed one by one), or campaign.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "api",
                                "app",
                                "mcp",
                                "campaign"
                            ]
                        },
                        "example": "api"
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "Started at or after (ISO 8601).",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "example": "2026-10-01T00:00:00+03:00"
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "Started at or before (ISO 8601).",
                        "schema": {
                            "type": "string",
                            "format": "date-time"
                        },
                        "example": "2026-10-07T23:59:59+03:00"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Page size (max 100).",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 25
                        },
                        "example": 25
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "description": "The `next_cursor` of the previous page.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "eyJpZCI6ODEyMzQsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of calls.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "A page of calls.",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "This page.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/Call"
                                                    }
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Pass as `cursor` for the next page; null on the last."
                                                },
                                                "has_more": {
                                                    "type": "boolean",
                                                    "description": "There is another page."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 81234,
                                                "room_name": "out-7f3c2a",
                                                "direction": "outbound",
                                                "status": "ended",
                                                "outcome": "answered",
                                                "answered": true,
                                                "from": "+255746000111",
                                                "to": "+255712345678",
                                                "mode": "message",
                                                "agent_config_id": null,
                                                "source": "api",
                                                "started_at": "2026-10-07T10:00:00+03:00",
                                                "answered_at": "2026-10-07T10:00:07+03:00",
                                                "ended_at": "2026-10-07T10:00:31+03:00",
                                                "duration_seconds": 24,
                                                "sip_status_code": null,
                                                "keys_pressed": [
                                                    {
                                                        "digit": "1",
                                                        "action": "confirm",
                                                        "label": "Thibitisha",
                                                        "at": "2026-10-07T07:00:21Z"
                                                    }
                                                ],
                                                "recording_available": false,
                                                "transcript_available": false,
                                                "request": {
                                                    "external_ref": "order-A1023",
                                                    "purpose": null,
                                                    "variables": {
                                                        "jina": "Amina",
                                                        "oda": "A1023"
                                                    },
                                                    "estimated_cost": 87
                                                },
                                                "campaign": null
                                            }
                                        ],
                                        "next_cursor": null,
                                        "has_more": false
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "calls.history.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/calls/{id}": {
            "get": {
                "tags": [
                    "Calls"
                ],
                "operationId": "v3CallShow",
                "summary": "Read a call",
                "description": "One call: status, outcome, keys pressed with what each meant, and the campaign person or API request it belongs to. Needs `calls.history.view`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call id.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 81234
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The call.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/Call",
                                            "description": "The call."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": 81234,
                                        "room_name": "out-7f3c2a",
                                        "direction": "outbound",
                                        "status": "ended",
                                        "outcome": "answered",
                                        "answered": true,
                                        "from": "+255746000111",
                                        "to": "+255712345678",
                                        "mode": "message",
                                        "agent_config_id": null,
                                        "source": "api",
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "answered_at": "2026-10-07T10:00:07+03:00",
                                        "ended_at": "2026-10-07T10:00:31+03:00",
                                        "duration_seconds": 24,
                                        "sip_status_code": null,
                                        "keys_pressed": [
                                            {
                                                "digit": "1",
                                                "action": "confirm",
                                                "label": "Thibitisha",
                                                "at": "2026-10-07T07:00:21Z"
                                            }
                                        ],
                                        "recording_available": false,
                                        "transcript_available": false,
                                        "request": {
                                            "external_ref": "order-A1023",
                                            "purpose": null,
                                            "variables": {
                                                "jina": "Amina",
                                                "oda": "A1023"
                                            },
                                            "estimated_cost": 87
                                        },
                                        "campaign": null
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "calls.history.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/calls/{id}/transcript": {
            "get": {
                "tags": [
                    "Calls"
                ],
                "operationId": "v3CallTranscript",
                "summary": "Read a call's transcript",
                "description": "What was said, line by line, when the call was transcribed. Needs `calls.transcripts.view`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call id.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 81234
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The transcript.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The transcript.",
                                            "properties": {
                                                "call_id": {
                                                    "type": "integer",
                                                    "description": "The call."
                                                },
                                                "lines": {
                                                    "type": "array",
                                                    "description": "What was said, in order.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One line.",
                                                        "properties": {
                                                            "speaker": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Who said it: agent, customer, user \u2026"
                                                            },
                                                            "text": {
                                                                "type": "string",
                                                                "description": "What was said."
                                                            },
                                                            "at": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "When (ISO 8601)."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "call_id": 81234,
                                        "lines": [
                                            {
                                                "speaker": "agent",
                                                "text": "Habari Amina, ninapiga kuhusu oda yako A1023.",
                                                "at": "2026-10-07T10:00:00+03:00"
                                            },
                                            {
                                                "speaker": "customer",
                                                "text": "Ndiyo, nitaipokea kesho.",
                                                "at": "2026-10-07T10:00:12+03:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "calls.transcripts.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/calls/{id}/recordings": {
            "get": {
                "tags": [
                    "Calls"
                ],
                "operationId": "v3CallRecordings",
                "summary": "List a call's recordings",
                "description": "The call's recordings. `url` streams the audio with the same API key (or is the phone system's own link). Needs `calls.recordings.view`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call id.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 81234
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The recordings.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "The recordings.",
                                            "properties": {
                                                "call_id": {
                                                    "type": "integer",
                                                    "description": "The call."
                                                },
                                                "items": {
                                                    "type": "array",
                                                    "description": "The recordings.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One recording.",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "The recording id."
                                                            },
                                                            "status": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "complete, processing \u2026"
                                                            },
                                                            "duration_seconds": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ],
                                                                "description": "Length."
                                                            },
                                                            "mime_type": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "The audio type."
                                                            },
                                                            "url": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Where to fetch the audio; null while it is not ready."
                                                            },
                                                            "created_at": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "When it was made."
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "call_id": 81234,
                                        "items": [
                                            {
                                                "id": 77,
                                                "status": "complete",
                                                "duration_seconds": 24,
                                                "mime_type": "audio/mpeg",
                                                "url": "https://business.momo.tz/api/v3/calls/81234/recordings/77/media",
                                                "created_at": "2026-10-07T10:00:00+03:00"
                                            }
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "calls.recordings.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/calls/{id}/recordings/{recording}/media": {
            "get": {
                "tags": [
                    "Calls"
                ],
                "operationId": "v3CallRecordingMedia",
                "summary": "Download a recording",
                "description": "The recording's audio (MP3), with Range support. Needs `calls.recordings.view`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call id.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 81234
                    },
                    {
                        "name": "recording",
                        "in": "path",
                        "required": true,
                        "description": "The recording id from the recordings list.",
                        "schema": {
                            "type": "integer"
                        },
                        "example": 77
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The audio.",
                        "content": {
                            "audio/mpeg": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary",
                                    "description": "MP3 audio."
                                },
                                "example": "<MP3 audio>"
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "calls.recordings.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/estimate": {
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignEstimate",
                "summary": "Price a campaign",
                "description": "The estimate for a payload before anything is saved: how many people will really be called, the likely and the most it can cost, when it finishes inside calling hours, and whether the wallet is enough. Nobody is called. Needs `call-campaigns.create`.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CallCampaignPayload"
                            },
                            "example": {
                                "name": "Confirm orders \u00b7 7 Oct",
                                "goal": "confirm_orders",
                                "audience": {
                                    "type": "targets",
                                    "targets": [
                                        {
                                            "to": "+255712345678",
                                            "name": "Amina",
                                            "variables": {
                                                "oda": "A1023",
                                                "kiasi": "45,000"
                                            },
                                            "external_id": "order-A1023"
                                        },
                                        {
                                            "to": "0754000222",
                                            "name": "Juma",
                                            "variables": {
                                                "oda": "A1024",
                                                "kiasi": "12,500"
                                            },
                                            "external_id": "order-A1024"
                                        }
                                    ]
                                },
                                "mode": "message",
                                "message": {
                                    "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi.",
                                    "language": "sw"
                                },
                                "keys": {
                                    "1": {
                                        "action": "confirm",
                                        "label": "Thibitisha"
                                    },
                                    "2": {
                                        "action": "tag",
                                        "label": "Ghairi",
                                        "tag": "cancelled_order"
                                    }
                                },
                                "when": {
                                    "start": "now"
                                },
                                "advanced": {
                                    "external_ref": "cod-2026-10-07",
                                    "cooldown_hours": 0
                                },
                                "consent": true
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The estimate.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaignEstimate",
                                            "description": "The estimate."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "people": 3,
                                        "mode": "message",
                                        "currency": "TZS",
                                        "minutes": 0.4,
                                        "minutes_likely": 0.4,
                                        "minutes_max": 4.5,
                                        "likely_cost": 156.6,
                                        "max_cost": 391.5,
                                        "hold_amount": 391.5,
                                        "per_person_reached": 87,
                                        "per_call_max": 130.5,
                                        "lines": 1,
                                        "starts_at": "2026-10-07T10:00:00+03:00",
                                        "finishes_at": "2026-10-07T10:01:41+03:00",
                                        "duration_minutes": 2,
                                        "calling_window": {
                                            "timezone": "Africa/Dar_es_Salaam",
                                            "days": [
                                                1,
                                                2,
                                                3,
                                                4,
                                                5,
                                                6
                                            ],
                                            "from": "08:00",
                                            "to": "20:00",
                                            "enforced": true
                                        },
                                        "calling_window_label": "08:00\u201320:00 Mon\u2013Sat",
                                        "wallet": {
                                            "available": 50000,
                                            "postpaid": false,
                                            "held": 0,
                                            "balance": 50000,
                                            "currency": "TZS"
                                        },
                                        "wallet_available": 50000,
                                        "enough": true,
                                        "enough_for_likely": true,
                                        "shortfall": 0,
                                        "short_by": 0,
                                        "budget_cap": null,
                                        "assumptions": {
                                            "answer_rate": 0.6,
                                            "talk_seconds": 22,
                                            "max_call_seconds": 90,
                                            "ring_seconds": 30
                                        },
                                        "rates": {
                                            "per_minute": 85,
                                            "connect_fee": 2,
                                            "increment_seconds": 30,
                                            "ai_per_minute": 0
                                        },
                                        "audience": {
                                            "total": 3,
                                            "kept": 3,
                                            "duplicates": 0,
                                            "invalid": [],
                                            "invalid_count": 0,
                                            "opted_out": 0,
                                            "cooldown": 0,
                                            "cooldown_hours": 24
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.create",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns": {
            "get": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignList",
                "summary": "List call campaigns",
                "description": "The workspace's call campaigns, newest first, a page at a time. Needs `call-campaigns.view`.",
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "One status, or active (draft, scheduled, running, paused) / finished (completed, cancelled, failed).",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "draft",
                                "scheduled",
                                "running",
                                "paused",
                                "completed",
                                "cancelled",
                                "failed",
                                "active",
                                "finished"
                            ]
                        },
                        "example": "active"
                    },
                    {
                        "name": "external_ref",
                        "in": "query",
                        "required": false,
                        "description": "The campaign with this reference.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "cod-confirmations"
                    },
                    {
                        "name": "source",
                        "in": "query",
                        "required": false,
                        "description": "Where it was made: web, api, mcp, automation or app.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "web",
                                "api",
                                "mcp",
                                "automation",
                                "app"
                            ]
                        },
                        "example": "api"
                    },
                    {
                        "name": "goal",
                        "in": "query",
                        "required": false,
                        "description": "Only this goal.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "confirm_orders"
                    },
                    {
                        "name": "is_rolling",
                        "in": "query",
                        "required": false,
                        "description": "true for always-on campaigns only, false for the others.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "true",
                                "false"
                            ]
                        },
                        "example": "true"
                    },
                    {
                        "name": "q",
                        "in": "query",
                        "required": false,
                        "description": "Part of the name.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "Confirm"
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Page size (max 100).",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 25
                        },
                        "example": 25
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "description": "The `next_cursor` of the previous page.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "eyJpZCI6ODEyMzQsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of campaigns.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "A page of campaigns.",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "This page.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/CallCampaign"
                                                    }
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Pass as `cursor` for the next page; null on the last."
                                                },
                                                "has_more": {
                                                    "type": "boolean",
                                                    "description": "There is another page."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                                "name": "Confirm orders",
                                                "goal": "confirm_orders",
                                                "status": "running",
                                                "state": "calling",
                                                "state_label": "Calling",
                                                "needs_attention": false,
                                                "pause_reason": null,
                                                "attention_reason": null,
                                                "mode": "message",
                                                "is_rolling": true,
                                                "purpose_class": "transactional",
                                                "source": "api",
                                                "external_ref": "cod-confirmations",
                                                "people": 120,
                                                "counts": {
                                                    "all": 120,
                                                    "waiting": 14,
                                                    "calling": 2,
                                                    "reached": 31,
                                                    "pressed": 58,
                                                    "pressed_by_digit": {
                                                        "1": 51,
                                                        "2": 7
                                                    },
                                                    "reached_total": 89,
                                                    "callback": 0,
                                                    "not_reached": 15,
                                                    "opted_out": 0,
                                                    "wrong_number": 0,
                                                    "skipped": 0
                                                },
                                                "spent": 7743,
                                                "held": 2088,
                                                "likely_cost": 6264,
                                                "currency": "TZS",
                                                "message": {
                                                    "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                    "audio_asset_id": null,
                                                    "voice_id": null,
                                                    "voice_model": null,
                                                    "language": "sw",
                                                    "repeat": 1
                                                },
                                                "keys": {
                                                    "1": {
                                                        "action": "confirm",
                                                        "label": "Thibitisha"
                                                    },
                                                    "2": {
                                                        "action": "tag",
                                                        "label": "Ghairi",
                                                        "tag": "cancelled_order"
                                                    },
                                                    "9": {
                                                        "action": "opt_out",
                                                        "label": "Usipigiwe tena / Stop calling me"
                                                    }
                                                },
                                                "ivr_flow_id": null,
                                                "agent_config_id": null,
                                                "answer_fields": [],
                                                "settings": {
                                                    "calling_window": {
                                                        "timezone": "Africa/Dar_es_Salaam",
                                                        "days": [
                                                            1,
                                                            2,
                                                            3,
                                                            4,
                                                            5,
                                                            6
                                                        ],
                                                        "from": "08:00",
                                                        "to": "20:00",
                                                        "enforced": true
                                                    },
                                                    "max_tries": 3,
                                                    "ring_seconds": 30,
                                                    "lines": null,
                                                    "from_number": null,
                                                    "stop_rule": "call_everyone",
                                                    "max_call_seconds": 90,
                                                    "record_calls": false,
                                                    "cooldown_hours": 0,
                                                    "budget_cap": null
                                                },
                                                "connections": {
                                                    "leads": {
                                                        "answer_key": "interested",
                                                        "stage": "qualified",
                                                        "note": true
                                                    }
                                                },
                                                "scheduled_at": null,
                                                "started_at": "2026-10-07T10:00:00+03:00",
                                                "paused_at": null,
                                                "finished_at": null,
                                                "created_at": "2026-10-07T10:00:00+03:00",
                                                "updated_at": "2026-10-07T10:00:00+03:00"
                                            }
                                        ],
                                        "next_cursor": null,
                                        "has_more": false
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.view",
                "x-permission-scope": "controller"
            },
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignCreate",
                "summary": "Create a call campaign",
                "description": "Creates a campaign from the composer payload: a goal, who (a contact group, pasted numbers, `targets` with their own details and your `external_id`, a Daftari table filter, or lead stages), what they hear and when. `when.start` now (the default) starts calling inside calling hours; at schedules it; draft saves it. A repeated `advanced.external_ref` returns the campaign already made (200) and changes nothing. Starting now when the wallet cannot pay is a 402 with the estimate and nothing is made. `advanced.is_rolling: true` makes an always-on campaign that may open with nobody. Needs `call-campaigns.create`.",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any unique string per intended action. A retry with the same key replays the first answer (24 h) instead of acting twice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "cod-A1023-confirm"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CallCampaignPayload"
                            },
                            "example": {
                                "name": "Confirm orders \u00b7 7 Oct",
                                "goal": "confirm_orders",
                                "audience": {
                                    "type": "targets",
                                    "targets": [
                                        {
                                            "to": "+255712345678",
                                            "name": "Amina",
                                            "variables": {
                                                "oda": "A1023",
                                                "kiasi": "45,000"
                                            },
                                            "external_id": "order-A1023"
                                        },
                                        {
                                            "to": "0754000222",
                                            "name": "Juma",
                                            "variables": {
                                                "oda": "A1024",
                                                "kiasi": "12,500"
                                            },
                                            "external_id": "order-A1024"
                                        }
                                    ]
                                },
                                "mode": "message",
                                "message": {
                                    "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi.",
                                    "language": "sw"
                                },
                                "keys": {
                                    "1": {
                                        "action": "confirm",
                                        "label": "Thibitisha"
                                    },
                                    "2": {
                                        "action": "tag",
                                        "label": "Ghairi",
                                        "tag": "cancelled_order"
                                    }
                                },
                                "when": {
                                    "start": "now"
                                },
                                "advanced": {
                                    "external_ref": "cod-2026-10-07",
                                    "cooldown_hours": 0
                                },
                                "consent": true
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "A campaign with this `advanced.external_ref` already existed; it is returned unchanged.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The existing campaign."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "The wallet cannot pay for it. `details.estimate` is the full estimate; nothing was started.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The wallet cannot pay for this campaign: it needs about TZS 391.50 and TZS 20.00 is available. Top up and try again.",
                                    "code": "insufficient_balance",
                                    "details": {
                                        "required": 391.5,
                                        "available": 20,
                                        "short_by": 371.5,
                                        "currency": "TZS",
                                        "estimate": {
                                            "people": 3,
                                            "mode": "message",
                                            "currency": "TZS",
                                            "minutes": 0.4,
                                            "minutes_likely": 0.4,
                                            "minutes_max": 4.5,
                                            "likely_cost": 156.6,
                                            "max_cost": 391.5,
                                            "hold_amount": 391.5,
                                            "per_person_reached": 87,
                                            "per_call_max": 130.5,
                                            "lines": 1,
                                            "starts_at": "2026-10-07T10:00:00+03:00",
                                            "finishes_at": "2026-10-07T10:01:41+03:00",
                                            "duration_minutes": 2,
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "calling_window_label": "08:00\u201320:00 Mon\u2013Sat",
                                            "wallet": {
                                                "available": 50000,
                                                "postpaid": false,
                                                "held": 0,
                                                "balance": 50000,
                                                "currency": "TZS"
                                            },
                                            "wallet_available": 50000,
                                            "enough": true,
                                            "enough_for_likely": true,
                                            "shortfall": 0,
                                            "short_by": 0,
                                            "budget_cap": null,
                                            "assumptions": {
                                                "answer_rate": 0.6,
                                                "talk_seconds": 22,
                                                "max_call_seconds": 90,
                                                "ring_seconds": 30
                                            },
                                            "rates": {
                                                "per_minute": 85,
                                                "connect_fee": 2,
                                                "increment_seconds": 30,
                                                "ai_per_minute": 0
                                            },
                                            "audience": {
                                                "total": 3,
                                                "kept": 3,
                                                "duplicates": 0,
                                                "invalid": [],
                                                "invalid_count": 0,
                                                "opted_out": 0,
                                                "cooldown": 0,
                                                "cooldown_hours": 24
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.create",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}": {
            "get": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignShow",
                "summary": "Read a call campaign",
                "description": "One campaign: its state and why it waits, what people hear, its settings, the counts by result, money spent and held. Needs `call-campaigns.view`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The campaign.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.view",
                "x-permission-scope": "controller"
            },
            "patch": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignUpdate",
                "summary": "Change a draft or scheduled campaign",
                "description": "Changes what is sent; a new `audience` replaces the people. Only a draft or a scheduled campaign can change (409 otherwise). A change never starts a campaign (`action: start_now` / `when.start: now` is a 422): start it with POST \u2026/start, which checks the wallet. Needs `call-campaigns.manage`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/CallCampaignPayload"
                            },
                            "example": {
                                "name": "Confirm orders \u00b7 evening",
                                "when": {
                                    "start": "at",
                                    "at": "2026-10-07T17:00:00+03:00"
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The campaign as it now is.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "Not a draft or scheduled campaign.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Only a draft or a scheduled campaign can be changed. Pause, stop or run it again instead.",
                                    "code": "invalid_state",
                                    "details": {
                                        "status": "running"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.manage",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}/start": {
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignStart",
                "summary": "Start a campaign now",
                "description": "Starts a draft or scheduled campaign now (inside calling hours). A draft never confirmed needs `consent: true`. 402 with the estimate when the wallet cannot pay for the people still to call. Needs `call-campaigns.manage`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any unique string per intended action. A retry with the same key replays the first answer (24 h) instead of acting twice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "cod-A1023-confirm"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The campaign as it now is.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The campaign's state does not allow this.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Only a calling campaign can be paused.",
                                    "code": "invalid_state",
                                    "details": {
                                        "status": "paused"
                                    }
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "The wallet cannot pay for it. `details.estimate` is the full estimate; nothing was started.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The wallet cannot pay for this campaign: it needs about TZS 391.50 and TZS 20.00 is available. Top up and try again.",
                                    "code": "insufficient_balance",
                                    "details": {
                                        "required": 391.5,
                                        "available": 20,
                                        "short_by": 371.5,
                                        "currency": "TZS",
                                        "estimate": {
                                            "people": 3,
                                            "mode": "message",
                                            "currency": "TZS",
                                            "minutes": 0.4,
                                            "minutes_likely": 0.4,
                                            "minutes_max": 4.5,
                                            "likely_cost": 156.6,
                                            "max_cost": 391.5,
                                            "hold_amount": 391.5,
                                            "per_person_reached": 87,
                                            "per_call_max": 130.5,
                                            "lines": 1,
                                            "starts_at": "2026-10-07T10:00:00+03:00",
                                            "finishes_at": "2026-10-07T10:01:41+03:00",
                                            "duration_minutes": 2,
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "calling_window_label": "08:00\u201320:00 Mon\u2013Sat",
                                            "wallet": {
                                                "available": 50000,
                                                "postpaid": false,
                                                "held": 0,
                                                "balance": 50000,
                                                "currency": "TZS"
                                            },
                                            "wallet_available": 50000,
                                            "enough": true,
                                            "enough_for_likely": true,
                                            "shortfall": 0,
                                            "short_by": 0,
                                            "budget_cap": null,
                                            "assumptions": {
                                                "answer_rate": 0.6,
                                                "talk_seconds": 22,
                                                "max_call_seconds": 90,
                                                "ring_seconds": 30
                                            },
                                            "rates": {
                                                "per_minute": 85,
                                                "connect_fee": 2,
                                                "increment_seconds": 30,
                                                "ai_per_minute": 0
                                            },
                                            "audience": {
                                                "total": 3,
                                                "kept": 3,
                                                "duplicates": 0,
                                                "invalid": [],
                                                "invalid_count": 0,
                                                "opted_out": 0,
                                                "cooldown": 0,
                                                "cooldown_hours": 24
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "Consent was never given.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Send \"consent\": true \u2014 these are your customers and they agreed to hear from you \u2014 to start this campaign.",
                                    "code": "consent_required"
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Only for a draft never confirmed.",
                                "properties": {
                                    "consent": {
                                        "type": "boolean",
                                        "description": "These are your customers and they agreed to hear from you."
                                    }
                                }
                            },
                            "example": {
                                "consent": true
                            }
                        }
                    }
                },
                "x-permission": "call-campaigns.manage",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}/pause": {
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignPause",
                "summary": "Pause a campaign",
                "description": "Nobody new is rung; calls already ringing finish. Sends `call_campaign.paused` with reason manual. Needs `call-campaigns.manage`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The campaign as it now is.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The campaign's state does not allow this.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Only a calling campaign can be paused.",
                                    "code": "invalid_state",
                                    "details": {
                                        "status": "paused"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.manage",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}/resume": {
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignResume",
                "summary": "Resume a paused campaign",
                "description": "Calls again inside calling hours, whatever paused it. 402 with the estimate when the wallet cannot carry on. Needs `call-campaigns.manage`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any unique string per intended action. A retry with the same key replays the first answer (24 h) instead of acting twice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "cod-A1023-confirm"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The campaign as it now is.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The campaign's state does not allow this.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Only a calling campaign can be paused.",
                                    "code": "invalid_state",
                                    "details": {
                                        "status": "paused"
                                    }
                                }
                            }
                        }
                    },
                    "402": {
                        "description": "The wallet cannot pay for it. `details.estimate` is the full estimate; nothing was started.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "The wallet cannot pay for this campaign: it needs about TZS 391.50 and TZS 20.00 is available. Top up and try again.",
                                    "code": "insufficient_balance",
                                    "details": {
                                        "required": 391.5,
                                        "available": 20,
                                        "short_by": 371.5,
                                        "currency": "TZS",
                                        "estimate": {
                                            "people": 3,
                                            "mode": "message",
                                            "currency": "TZS",
                                            "minutes": 0.4,
                                            "minutes_likely": 0.4,
                                            "minutes_max": 4.5,
                                            "likely_cost": 156.6,
                                            "max_cost": 391.5,
                                            "hold_amount": 391.5,
                                            "per_person_reached": 87,
                                            "per_call_max": 130.5,
                                            "lines": 1,
                                            "starts_at": "2026-10-07T10:00:00+03:00",
                                            "finishes_at": "2026-10-07T10:01:41+03:00",
                                            "duration_minutes": 2,
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "calling_window_label": "08:00\u201320:00 Mon\u2013Sat",
                                            "wallet": {
                                                "available": 50000,
                                                "postpaid": false,
                                                "held": 0,
                                                "balance": 50000,
                                                "currency": "TZS"
                                            },
                                            "wallet_available": 50000,
                                            "enough": true,
                                            "enough_for_likely": true,
                                            "shortfall": 0,
                                            "short_by": 0,
                                            "budget_cap": null,
                                            "assumptions": {
                                                "answer_rate": 0.6,
                                                "talk_seconds": 22,
                                                "max_call_seconds": 90,
                                                "ring_seconds": 30
                                            },
                                            "rates": {
                                                "per_minute": 85,
                                                "connect_fee": 2,
                                                "increment_seconds": 30,
                                                "ai_per_minute": 0
                                            },
                                            "audience": {
                                                "total": 3,
                                                "kept": 3,
                                                "duplicates": 0,
                                                "invalid": [],
                                                "invalid_count": 0,
                                                "opted_out": 0,
                                                "cooldown": 0,
                                                "cooldown_hours": 24
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.manage",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}/cancel": {
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignCancel",
                "summary": "Stop a campaign for good",
                "description": "Everyone not yet called is skipped and the hold is released; it cannot be restarted. Live calls are hung up unless `let_calls_finish`. Sends `call_campaign.completed` with state stopped. Needs `call-campaigns.manage`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The campaign as it now is.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "$ref": "#/components/schemas/CallCampaign",
                                            "description": "The campaign as it now is."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                        "name": "Confirm orders",
                                        "goal": "confirm_orders",
                                        "status": "running",
                                        "state": "calling",
                                        "state_label": "Calling",
                                        "needs_attention": false,
                                        "pause_reason": null,
                                        "attention_reason": null,
                                        "mode": "message",
                                        "is_rolling": true,
                                        "purpose_class": "transactional",
                                        "source": "api",
                                        "external_ref": "cod-confirmations",
                                        "people": 120,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        },
                                        "spent": 7743,
                                        "held": 2088,
                                        "likely_cost": 6264,
                                        "currency": "TZS",
                                        "message": {
                                            "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                            "audio_asset_id": null,
                                            "voice_id": null,
                                            "voice_model": null,
                                            "language": "sw",
                                            "repeat": 1
                                        },
                                        "keys": {
                                            "1": {
                                                "action": "confirm",
                                                "label": "Thibitisha"
                                            },
                                            "2": {
                                                "action": "tag",
                                                "label": "Ghairi",
                                                "tag": "cancelled_order"
                                            },
                                            "9": {
                                                "action": "opt_out",
                                                "label": "Usipigiwe tena / Stop calling me"
                                            }
                                        },
                                        "ivr_flow_id": null,
                                        "agent_config_id": null,
                                        "answer_fields": [],
                                        "settings": {
                                            "calling_window": {
                                                "timezone": "Africa/Dar_es_Salaam",
                                                "days": [
                                                    1,
                                                    2,
                                                    3,
                                                    4,
                                                    5,
                                                    6
                                                ],
                                                "from": "08:00",
                                                "to": "20:00",
                                                "enforced": true
                                            },
                                            "max_tries": 3,
                                            "ring_seconds": 30,
                                            "lines": null,
                                            "from_number": null,
                                            "stop_rule": "call_everyone",
                                            "max_call_seconds": 90,
                                            "record_calls": false,
                                            "cooldown_hours": 0,
                                            "budget_cap": null
                                        },
                                        "connections": {
                                            "leads": {
                                                "answer_key": "interested",
                                                "stage": "qualified",
                                                "note": true
                                            }
                                        },
                                        "scheduled_at": null,
                                        "started_at": "2026-10-07T10:00:00+03:00",
                                        "paused_at": null,
                                        "finished_at": null,
                                        "created_at": "2026-10-07T10:00:00+03:00",
                                        "updated_at": "2026-10-07T10:00:00+03:00"
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The campaign's state does not allow this.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "Only a calling campaign can be paused.",
                                    "code": "invalid_state",
                                    "details": {
                                        "status": "paused"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "requestBody": {
                    "required": false,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "How to stop.",
                                "properties": {
                                    "let_calls_finish": {
                                        "type": "boolean",
                                        "description": "Let calls already ringing or talking end on their own (default false)."
                                    }
                                }
                            },
                            "example": {
                                "let_calls_finish": true
                            }
                        }
                    }
                },
                "x-permission": "call-campaigns.manage",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}/targets": {
            "get": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignTargets",
                "summary": "Results per person",
                "description": "The campaign's people in list order with their result, a page at a time: follow `next_cursor`, or start at person #N with `position`. Filter by `result` or find one by `external_id`. `counts` are the totals by result. Needs `call-campaigns.view`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    },
                    {
                        "name": "result",
                        "in": "query",
                        "required": false,
                        "description": "all, reached, pressed, not_reached, waiting, calling, opted_out, wrong_number, callback or skipped.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "all",
                                "reached",
                                "pressed",
                                "not_reached",
                                "waiting",
                                "calling",
                                "opted_out",
                                "wrong_number",
                                "callback",
                                "skipped"
                            ],
                            "default": "all"
                        },
                        "example": "pressed"
                    },
                    {
                        "name": "external_id",
                        "in": "query",
                        "required": false,
                        "description": "The person with your id.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "order-A1023"
                    },
                    {
                        "name": "position",
                        "in": "query",
                        "required": false,
                        "description": "Start at person #N (1-based); ignored with a cursor.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        },
                        "example": 501
                    },
                    {
                        "name": "limit",
                        "in": "query",
                        "required": false,
                        "description": "Page size (max 100).",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100,
                            "default": 50
                        },
                        "example": 50
                    },
                    {
                        "name": "cursor",
                        "in": "query",
                        "required": false,
                        "description": "The `next_cursor` of the previous page.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "eyJpZCI6ODEyMzQsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "A page of people.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "A page of people.",
                                            "properties": {
                                                "items": {
                                                    "type": "array",
                                                    "description": "This page.",
                                                    "items": {
                                                        "$ref": "#/components/schemas/CallCampaignTarget"
                                                    }
                                                },
                                                "next_cursor": {
                                                    "type": [
                                                        "string",
                                                        "null"
                                                    ],
                                                    "description": "Pass as `cursor` for the next page; null on the last."
                                                },
                                                "has_more": {
                                                    "type": "boolean",
                                                    "description": "There is another page."
                                                },
                                                "counts": {
                                                    "$ref": "#/components/schemas/CallCampaignCounts",
                                                    "description": "Totals by result."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "items": [
                                            {
                                                "id": 5501,
                                                "position": 87,
                                                "to": "+255712345678",
                                                "name": "Amina J.",
                                                "external_id": "order-A1023",
                                                "contact_id": null,
                                                "result": "pressed",
                                                "result_label": "Pressed 1",
                                                "final": true,
                                                "tries": 1,
                                                "max_tries": 3,
                                                "next_try_at": null,
                                                "keys_pressed": [
                                                    "1"
                                                ],
                                                "answers": {
                                                    "confirmed": true
                                                },
                                                "summary": null,
                                                "variables": {
                                                    "jina": "Amina J.",
                                                    "oda": "A1023",
                                                    "kiasi": "45,000"
                                                },
                                                "last_call_id": 81234,
                                                "last_call_at": "2026-10-07T10:00:00+03:00",
                                                "cost": 87,
                                                "created_at": "2026-10-07T10:00:00+03:00"
                                            }
                                        ],
                                        "next_cursor": null,
                                        "has_more": false,
                                        "counts": {
                                            "all": 120,
                                            "waiting": 14,
                                            "calling": 2,
                                            "reached": 31,
                                            "pressed": 58,
                                            "pressed_by_digit": {
                                                "1": 51,
                                                "2": 7
                                            },
                                            "reached_total": 89,
                                            "callback": 0,
                                            "not_reached": 15,
                                            "opted_out": 0,
                                            "wrong_number": 0,
                                            "skipped": 0
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.view",
                "x-permission-scope": "controller"
            }
        },
        "/api/v3/call-campaigns/{id}/targets/batch": {
            "post": {
                "tags": [
                    "Call campaigns"
                ],
                "operationId": "v3CallCampaignTargetsBatch",
                "summary": "Add people to a campaign",
                "description": "Adds people to a campaign that has not ended \u2014 the front door of an always-on campaign (one call per new order). JSON `targets`, or a CSV / Excel `file` (the daily file). Idempotent per `external_id`: one already in the campaign is not added again and comes back under `existing`; without one, a number still waiting is not added twice. Cleaned like any audience. 201 when someone was added, 200 when nobody new was. Needs `call-campaigns.manage`.",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The call campaign id.",
                        "schema": {
                            "type": "string",
                            "format": "uuid"
                        },
                        "example": "01928c3e-7a1b-7c2d-9e0f-123456789abc"
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": false,
                        "description": "Any unique string per intended action. A retry with the same key replays the first answer (24 h) instead of acting twice.",
                        "schema": {
                            "type": "string",
                            "maxLength": 255
                        },
                        "example": "cod-A1023-confirm"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "The people.",
                                "properties": {
                                    "targets": {
                                        "type": "array",
                                        "description": "The people to add (\u2264 20,000).",
                                        "items": {
                                            "type": "object",
                                            "description": "One person.",
                                            "properties": {
                                                "to": {
                                                    "type": "string",
                                                    "description": "Their number."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "description": "Their name."
                                                },
                                                "variables": {
                                                    "type": "object",
                                                    "description": "Their details.",
                                                    "additionalProperties": {
                                                        "type": "string",
                                                        "description": "A detail value."
                                                    }
                                                },
                                                "external_id": {
                                                    "type": "string",
                                                    "description": "Your id for them (\u2264 128); the same one is never added twice."
                                                }
                                            }
                                        }
                                    }
                                },
                                "required": [
                                    "targets"
                                ]
                            },
                            "example": {
                                "targets": [
                                    {
                                        "to": "+255712000111",
                                        "name": "Neema",
                                        "variables": {
                                            "oda": "A1025",
                                            "kiasi": "30,000"
                                        },
                                        "external_id": "order-A1025"
                                    },
                                    {
                                        "to": "+255712345678",
                                        "external_id": "order-A1023"
                                    }
                                ]
                            }
                        },
                        "multipart/form-data": {
                            "schema": {
                                "type": "object",
                                "description": "A file of people.",
                                "properties": {
                                    "file": {
                                        "type": "string",
                                        "description": "CSV or Excel; a phone column, optionally a name column and any detail columns.",
                                        "format": "binary"
                                    },
                                    "phone_column": {
                                        "type": "string",
                                        "description": "The phone column's header, when it is not obvious."
                                    },
                                    "name_column": {
                                        "type": "string",
                                        "description": "The name column's header."
                                    }
                                },
                                "required": [
                                    "file"
                                ]
                            },
                            "example": {
                                "phone_column": "simu",
                                "name_column": "jina"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "People were added.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "What happened.",
                                            "properties": {
                                                "added": {
                                                    "type": "integer",
                                                    "description": "People added."
                                                },
                                                "targets": {
                                                    "type": "array",
                                                    "description": "The people added.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One person added (or already there).",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Their row id."
                                                            },
                                                            "external_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Your id for them."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "Their number."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "Their place in the list (new rows only)."
                                                            },
                                                            "result": {
                                                                "type": "string",
                                                                "description": "Their result so far (existing rows only)."
                                                            }
                                                        }
                                                    }
                                                },
                                                "existing": {
                                                    "type": "array",
                                                    "description": "People already in the campaign (same external_id, or the same number still waiting), not added again.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One person added (or already there).",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Their row id."
                                                            },
                                                            "external_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Your id for them."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "Their number."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "Their place in the list (new rows only)."
                                                            },
                                                            "result": {
                                                                "type": "string",
                                                                "description": "Their result so far (existing rows only)."
                                                            }
                                                        }
                                                    }
                                                },
                                                "report": {
                                                    "type": "object",
                                                    "description": "The cleaning report: total, kept, duplicates, invalid (by row), opted_out, cooldown, already_in_campaign.",
                                                    "additionalProperties": true
                                                },
                                                "campaign": {
                                                    "$ref": "#/components/schemas/CallCampaign",
                                                    "description": "The campaign as it now is."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "added": 1,
                                        "targets": [
                                            {
                                                "id": 5502,
                                                "external_id": "order-A1025",
                                                "to": "+255712000111",
                                                "position": 121
                                            }
                                        ],
                                        "existing": [
                                            {
                                                "id": 5501,
                                                "external_id": "order-A1023",
                                                "to": "+255712345678",
                                                "result": "pressed"
                                            }
                                        ],
                                        "report": {
                                            "total": 2,
                                            "kept": 2,
                                            "duplicates": 0,
                                            "invalid": [],
                                            "invalid_count": 0,
                                            "opted_out": 0,
                                            "cooldown": 0,
                                            "cooldown_hours": 0,
                                            "already_in_campaign": 1
                                        },
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "running",
                                            "state": "calling",
                                            "state_label": "Calling",
                                            "needs_attention": false,
                                            "pause_reason": null,
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": null,
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "200": {
                        "description": "Nobody new: everyone was already there (or was cleaned out).",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "description": "Always \"success\".",
                                            "enum": [
                                                "success"
                                            ]
                                        },
                                        "data": {
                                            "type": "object",
                                            "description": "What happened.",
                                            "properties": {
                                                "added": {
                                                    "type": "integer",
                                                    "description": "People added."
                                                },
                                                "targets": {
                                                    "type": "array",
                                                    "description": "The people added.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One person added (or already there).",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Their row id."
                                                            },
                                                            "external_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Your id for them."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "Their number."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "Their place in the list (new rows only)."
                                                            },
                                                            "result": {
                                                                "type": "string",
                                                                "description": "Their result so far (existing rows only)."
                                                            }
                                                        }
                                                    }
                                                },
                                                "existing": {
                                                    "type": "array",
                                                    "description": "People already in the campaign (same external_id, or the same number still waiting), not added again.",
                                                    "items": {
                                                        "type": "object",
                                                        "description": "One person added (or already there).",
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer",
                                                                "description": "Their row id."
                                                            },
                                                            "external_id": {
                                                                "type": [
                                                                    "string",
                                                                    "null"
                                                                ],
                                                                "description": "Your id for them."
                                                            },
                                                            "to": {
                                                                "type": "string",
                                                                "description": "Their number."
                                                            },
                                                            "position": {
                                                                "type": "integer",
                                                                "description": "Their place in the list (new rows only)."
                                                            },
                                                            "result": {
                                                                "type": "string",
                                                                "description": "Their result so far (existing rows only)."
                                                            }
                                                        }
                                                    }
                                                },
                                                "report": {
                                                    "type": "object",
                                                    "description": "The cleaning report: total, kept, duplicates, invalid (by row), opted_out, cooldown, already_in_campaign.",
                                                    "additionalProperties": true
                                                },
                                                "campaign": {
                                                    "$ref": "#/components/schemas/CallCampaign",
                                                    "description": "The campaign as it now is."
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "added": 0,
                                        "targets": [],
                                        "existing": [
                                            {
                                                "id": 5501,
                                                "external_id": "order-A1023",
                                                "to": "+255712345678",
                                                "result": "pressed"
                                            }
                                        ],
                                        "report": {
                                            "total": 2,
                                            "kept": 2,
                                            "duplicates": 0,
                                            "invalid": [],
                                            "invalid_count": 0,
                                            "opted_out": 0,
                                            "cooldown": 0,
                                            "cooldown_hours": 0,
                                            "already_in_campaign": 1
                                        },
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "running",
                                            "state": "calling",
                                            "state_label": "Calling",
                                            "needs_attention": false,
                                            "pause_reason": null,
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": null,
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "409": {
                        "description": "The campaign has ended.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/CallRefusalEnvelope"
                                },
                                "example": {
                                    "status": "error",
                                    "message": "This campaign has ended. Create a new one (or an always-on campaign) to call more people.",
                                    "code": "invalid_state",
                                    "details": {
                                        "status": "cancelled"
                                    }
                                }
                            }
                        }
                    },
                    "404": {
                        "$ref": "#/components/responses/NotFound"
                    },
                    "422": {
                        "$ref": "#/components/responses/ValidationFailed"
                    },
                    "401": {
                        "$ref": "#/components/responses/Unauthorized"
                    },
                    "403": {
                        "$ref": "#/components/responses/Forbidden"
                    },
                    "429": {
                        "$ref": "#/components/responses/RateLimited"
                    }
                },
                "x-permission": "call-campaigns.manage",
                "x-permission-scope": "controller"
            }
        },
        "/mcp": {
            "post": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpAccountEndpoint",
                "summary": "Call the account MCP server",
                "description": "The bare `/mcp` root, serving the **account** server \u2014 the cross-domain starting point, and what a person types when a client asks for a URL.\n\nIt exists because without it the whole OAuth handshake succeeds \u2014 discovery, consent, a real access token \u2014 and then the first `tools/call` 404s, which is the least debuggable failure there is.\n\nEverything below applies equally to `POST /mcp/v1/{server}`; connect a specific server there when you know which part of the business you want, because most clients fold the entire tool list into their context and connecting everything makes an assistant worse at choosing.",
                "x-generated-by": "php artisan mcp:manifest",
                "security": [
                    {
                        "McpBearerToken": []
                    },
                    {
                        "McpOAuth": [
                            "mcp:use"
                        ]
                    }
                ],
                "requestBody": {
                    "required": true,
                    "description": "A JSON-RPC 2.0 request. `Accept` must allow both `application/json` and `text/event-stream`.",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/JsonRpcRequest"
                            },
                            "examples": {
                                "initialize": {
                                    "summary": "1. initialize \u2014 open the session",
                                    "description": "Sent once, first. Negotiates a protocol version and returns the server's instructions.",
                                    "value": {
                                        "jsonrpc": "2.0",
                                        "id": 1,
                                        "method": "initialize",
                                        "params": {
                                            "protocolVersion": "2025-06-18",
                                            "capabilities": {
                                                "roots": {
                                                    "listChanged": true
                                                }
                                            },
                                            "clientInfo": {
                                                "name": "my-agent",
                                                "version": "1.0.0"
                                            }
                                        }
                                    }
                                },
                                "toolsList": {
                                    "summary": "2. tools/list \u2014 discover what is here",
                                    "description": "The only way to learn the tool names. They are deliberately not in this OpenAPI document: what a credential can reach depends on the account, its modules and the granted scopes.",
                                    "value": {
                                        "jsonrpc": "2.0",
                                        "id": 2,
                                        "method": "tools/list"
                                    }
                                },
                                "toolsCall": {
                                    "summary": "3. tools/call \u2014 run one",
                                    "description": "`params.arguments` must satisfy that tool's `inputSchema` from `tools/list`.",
                                    "value": {
                                        "jsonrpc": "2.0",
                                        "id": 3,
                                        "method": "tools/call",
                                        "params": {
                                            "name": "list_ivr_flows",
                                            "arguments": {
                                                "search": "main"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The JSON-RPC result. A notification \u2014 a request with no `id` \u2014 is answered `202` with an empty body instead.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "examples": {
                                    "initialize": {
                                        "summary": "initialize",
                                        "value": {
                                            "jsonrpc": "2.0",
                                            "id": 1,
                                            "result": {
                                                "protocolVersion": "2025-06-18",
                                                "capabilities": {
                                                    "tools": {
                                                        "listChanged": false
                                                    },
                                                    "resources": {
                                                        "listChanged": false
                                                    },
                                                    "prompts": {
                                                        "listChanged": false
                                                    }
                                                },
                                                "serverInfo": {
                                                    "name": "Momo IVR",
                                                    "version": "1.0.0"
                                                },
                                                "instructions": "Build and edit the call flows (IVRs) that answer this business's phone lines. \u2026"
                                            }
                                        }
                                    },
                                    "toolsList": {
                                        "summary": "tools/list",
                                        "value": {
                                            "jsonrpc": "2.0",
                                            "id": 2,
                                            "result": {
                                                "tools": [
                                                    {
                                                        "name": "list_ivr_flows",
                                                        "title": "List Ivr Flows",
                                                        "description": "The call flows on this account, newest first.",
                                                        "inputSchema": {
                                                            "type": "object",
                                                            "properties": {
                                                                "search": {
                                                                    "type": "string",
                                                                    "description": "Filter by name."
                                                                }
                                                            }
                                                        },
                                                        "annotations": {
                                                            "readOnlyHint": false,
                                                            "destructiveHint": false,
                                                            "openWorldHint": false
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    "toolsCall": {
                                        "summary": "tools/call",
                                        "description": "A tool that fails cleanly still answers 200 \u2014 with `isError` true and a message the model is meant to act on.",
                                        "value": {
                                            "jsonrpc": "2.0",
                                            "id": 3,
                                            "result": {
                                                "content": [
                                                    {
                                                        "type": "text",
                                                        "text": "{\"flows\":[{\"id\":41,\"name\":\"Main line\",\"status\":\"published\"}]}"
                                                    }
                                                ],
                                                "isError": false
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "A notification was accepted. No body."
                    },
                    "401": {
                        "description": "No credential, or one that is expired or revoked. The `WWW-Authenticate` header points at the protected-resource document, which is what bootstraps the OAuth handshake.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32001,
                                        "message": "Authentication required.",
                                        "data": {
                                            "reason": "missing_token"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "The credential is valid but this server is out of reach \u2014 a capability that was not granted, a module switched off for the account, a suspended account, or a v3 API key used in place of an MCP credential. `data.reason` says which.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32002,
                                        "message": "This connection was not given access to Numbers. The account owner can add it by reconnecting.",
                                        "data": {
                                            "reason": "server_not_granted"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "More than 120 requests in a minute from this connection.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32003,
                                        "message": "Too many MCP requests from this connection. Wait a minute and retry \u2014 do not loop."
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The MCP surface is switched off platform-wide. Never cached \u2014 shutting it down is a database write that takes effect on the next request.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32002,
                                        "message": "The MCP surface is not enabled on this platform right now.",
                                        "data": {
                                            "reason": "surface_disabled"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    }
                }
            }
        },
        "/mcp/v1": {
            "get": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpListServers",
                "summary": "List the servers this credential can reach",
                "description": "What **this** credential can reach, which is not the same question as what exists: scopes differ per credential, and a capability the account holder did not grant leaves its server absent rather than merely unauthorized.\n\nThe public catalogue, for someone evaluating the platform before they have a token, is `GET /api-docs/mcp.json`.",
                "x-generated-by": "php artisan mcp:manifest",
                "security": [
                    {
                        "McpBearerToken": []
                    },
                    {
                        "McpOAuth": [
                            "mcp:use"
                        ]
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The servers, each marked reachable or not for this credential.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "account": {
                                            "type": [
                                                "string",
                                                "null"
                                            ],
                                            "description": "The account this credential belongs to."
                                        },
                                        "protocol": {
                                            "type": "string",
                                            "const": "mcp",
                                            "description": "Always \"mcp\"."
                                        },
                                        "transport": {
                                            "type": "string",
                                            "const": "streamable-http",
                                            "description": "The MCP transport these endpoints speak."
                                        },
                                        "servers": {
                                            "type": "array",
                                            "items": {
                                                "$ref": "#/components/schemas/ServerInfo"
                                            },
                                            "description": "Every mounted server, marked reachable or not for this credential."
                                        },
                                        "docs": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Where a person can read about all of this."
                                        }
                                    }
                                },
                                "example": {
                                    "account": "Workspace Alpha",
                                    "protocol": "mcp",
                                    "transport": "streamable-http",
                                    "servers": [
                                        {
                                            "key": "ivr",
                                            "name": "IVR",
                                            "description": "Build and edit call flows: read the graph, apply node operations, validate, simulate, version and assign to numbers.",
                                            "url": "https://business.momo.tz/mcp/v1/ivr",
                                            "available": true,
                                            "reason": null
                                        },
                                        {
                                            "key": "numbers",
                                            "name": "Numbers",
                                            "description": "Phone numbers: what you own, what is available, what one costs, and how to pay for it.",
                                            "url": "https://business.momo.tz/mcp/v1/numbers",
                                            "available": false,
                                            "reason": "This connection was not granted access to Numbers."
                                        }
                                    ],
                                    "docs": "https://business.momo.tz/api-docs#mcp"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "No credential, or one that is expired or revoked.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32001,
                                        "message": "Authentication required.",
                                        "data": {
                                            "reason": "missing_token"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The MCP surface is switched off platform-wide.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32002,
                                        "message": "The MCP surface is not enabled on this platform right now.",
                                        "data": {
                                            "reason": "surface_disabled"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    }
                }
            }
        },
        "/mcp/v1/{server}": {
            "post": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpServerEndpoint",
                "summary": "Call one MCP server",
                "description": "One server, one URL, one JSON-RPC endpoint. The tools it offers are discovered at runtime with `tools/list`; their arguments are a JSON Schema each, published for every server at `GET /api-docs/mcp.json`.\n\n| `server` | Name | What it covers |\n|---|---|---|\n| `ivr` | IVR | Build and edit call flows: read the graph, apply node operations, validate, simulate, version and assign to numbers. |\n| `flows` | Message flows | Build and edit WhatsApp conversation flows: nodes, edges, triggers, validation, simulation and analytics. |\n| `forms` | WhatsApp forms | Forms customers fill in inside WhatsApp: build them, check them with WhatsApp, publish, send to a customer, and read the answers. |\n| `data` | Data tables | The tables this business defined for itself and their records: read with filters, create/update/upsert rows, shape fields, run and save reports, and group related tables into folders with reports that read across them. Flows and IVRs read the same tables. |\n| `approvals` | Approvals | Decisions a person has been asked for before something happens: read the queue, read one in full with every comment on it, answer one. |\n| `payments` | Payments | Money this business collects from its customers: what has been asked for and where each one got to, one payment's whole timeline, asking a customer to pay, and refunds. Not the business's own Momo bill. |\n| `automations` | Automations | What happens without anybody there: the log of what has actually happened in the business, the subscriptions that react to it, and the schedules that run on a rhythm. |\n| `alerts` | Alerts & service levels | The business watching itself: the alert rules it wrote, the service-level promises and the clocks running against them, the risk rules that hold or refuse an action, and one log of everything that fired \u2014 including what reached nobody. |\n| `operations` | Operations | The named things this business can do \u2014 create a booking, register a customer, process a refund \u2014 each written down once, and the log of every time one ran. |\n| `studio` | Studio | Voice and audio: browse the voice library, generate speech, convert audio and publish it for use in an IVR. |\n| `numbers` | Numbers | Phone numbers: what you own, what is available, what one costs, and how to pay for it. |\n| `groups` | WhatsApp groups | Groups the business runs from its WhatsApp number: create, invite, post, approve joins, remove members. |\n| `agents` | Agents | Your own AI specialists: see the roster and ask one a question. |\n| `orders` | Orders | Customer orders across every platform: find, read, move status, request payment. |\n| `shop` | Shop | Products, their sizes and add-ons, brands and categories, plus the order tools. |\n| `tickets` | Tickets | Support tickets: create, update, assign, reply, labels and notifications. |\n| `kb` | Knowledge base | Your knowledge base: categories, search and full article text. |\n| `content` | Platform content | Public help articles, changelog, roadmap and system status. |\n| `calls` | Calls | Call history, recordings, transcripts, events and Call Studio scripts. |\n| `routing` | Call routing | Routing rules, ring groups, working hours and forwarding targets. |\n| `meetings` | Meetings | See and schedule meetings, and invite people to them. |\n| `messaging` | Messaging | Templates, sender IDs, campaigns, message history \u2014 and sending SMS and WhatsApp. |\n| `inbox` | Inbox | Customer conversations across WhatsApp, SMS, social and email \u2014 read, assign, reply, and send new mail. |\n| `comments` | Comments | Comments on your Facebook, Instagram and TikTok posts. |\n| `posts` | Posts | Social posts to Facebook, Instagram, TikTok, YouTube and LinkedIn: what is drafted, scheduled and sent; drafting a new one; scheduling or publishing it. |\n| `contacts` | Contacts | The contact book and groups. |\n| `leads` | Leads | Every potential customer at any stage: find a person's lead by any number or id, add or update one without duplicating, move its stage, label it, note what was said, and give it to someone to follow up. |\n| `overview` | Overview | The dashboard, business analytics, call stats and spend \u2014 how the business is doing. |\n| `accounts` | Connected accounts | The WhatsApp numbers, social profiles, mailboxes and SMS routes this business has connected, and what each can actually do. |\n| `navigate` | Finding things | Where pages and settings live in the app, and what each form asks for. |\n| `account` | Account | A cross-domain starting point: overview, search, fetch, and the most-used read tools. |",
                "x-generated-by": "php artisan mcp:manifest",
                "security": [
                    {
                        "McpBearerToken": []
                    },
                    {
                        "McpOAuth": [
                            "mcp:use"
                        ]
                    }
                ],
                "parameters": [
                    {
                        "name": "server",
                        "in": "path",
                        "required": true,
                        "description": "Which server to talk to.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "ivr",
                                "flows",
                                "forms",
                                "data",
                                "approvals",
                                "payments",
                                "automations",
                                "alerts",
                                "operations",
                                "studio",
                                "numbers",
                                "groups",
                                "agents",
                                "orders",
                                "shop",
                                "tickets",
                                "kb",
                                "content",
                                "calls",
                                "routing",
                                "meetings",
                                "messaging",
                                "inbox",
                                "comments",
                                "posts",
                                "contacts",
                                "leads",
                                "overview",
                                "accounts",
                                "navigate",
                                "account"
                            ]
                        },
                        "example": "ivr"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "description": "A JSON-RPC 2.0 request. `Accept` must allow both `application/json` and `text/event-stream`.",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/JsonRpcRequest"
                            },
                            "examples": {
                                "initialize": {
                                    "summary": "1. initialize \u2014 open the session",
                                    "description": "Sent once, first. Negotiates a protocol version and returns the server's instructions.",
                                    "value": {
                                        "jsonrpc": "2.0",
                                        "id": 1,
                                        "method": "initialize",
                                        "params": {
                                            "protocolVersion": "2025-06-18",
                                            "capabilities": {
                                                "roots": {
                                                    "listChanged": true
                                                }
                                            },
                                            "clientInfo": {
                                                "name": "my-agent",
                                                "version": "1.0.0"
                                            }
                                        }
                                    }
                                },
                                "toolsList": {
                                    "summary": "2. tools/list \u2014 discover what is here",
                                    "description": "The only way to learn the tool names. They are deliberately not in this OpenAPI document: what a credential can reach depends on the account, its modules and the granted scopes.",
                                    "value": {
                                        "jsonrpc": "2.0",
                                        "id": 2,
                                        "method": "tools/list"
                                    }
                                },
                                "toolsCall": {
                                    "summary": "3. tools/call \u2014 run one",
                                    "description": "`params.arguments` must satisfy that tool's `inputSchema` from `tools/list`.",
                                    "value": {
                                        "jsonrpc": "2.0",
                                        "id": 3,
                                        "method": "tools/call",
                                        "params": {
                                            "name": "list_ivr_flows",
                                            "arguments": {
                                                "search": "main"
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The JSON-RPC result. A notification \u2014 a request with no `id` \u2014 is answered `202` with an empty body instead.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "examples": {
                                    "initialize": {
                                        "summary": "initialize",
                                        "value": {
                                            "jsonrpc": "2.0",
                                            "id": 1,
                                            "result": {
                                                "protocolVersion": "2025-06-18",
                                                "capabilities": {
                                                    "tools": {
                                                        "listChanged": false
                                                    },
                                                    "resources": {
                                                        "listChanged": false
                                                    },
                                                    "prompts": {
                                                        "listChanged": false
                                                    }
                                                },
                                                "serverInfo": {
                                                    "name": "Momo IVR",
                                                    "version": "1.0.0"
                                                },
                                                "instructions": "Build and edit the call flows (IVRs) that answer this business's phone lines. \u2026"
                                            }
                                        }
                                    },
                                    "toolsList": {
                                        "summary": "tools/list",
                                        "value": {
                                            "jsonrpc": "2.0",
                                            "id": 2,
                                            "result": {
                                                "tools": [
                                                    {
                                                        "name": "list_ivr_flows",
                                                        "title": "List Ivr Flows",
                                                        "description": "The call flows on this account, newest first.",
                                                        "inputSchema": {
                                                            "type": "object",
                                                            "properties": {
                                                                "search": {
                                                                    "type": "string",
                                                                    "description": "Filter by name."
                                                                }
                                                            }
                                                        },
                                                        "annotations": {
                                                            "readOnlyHint": false,
                                                            "destructiveHint": false,
                                                            "openWorldHint": false
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    "toolsCall": {
                                        "summary": "tools/call",
                                        "description": "A tool that fails cleanly still answers 200 \u2014 with `isError` true and a message the model is meant to act on.",
                                        "value": {
                                            "jsonrpc": "2.0",
                                            "id": 3,
                                            "result": {
                                                "content": [
                                                    {
                                                        "type": "text",
                                                        "text": "{\"flows\":[{\"id\":41,\"name\":\"Main line\",\"status\":\"published\"}]}"
                                                    }
                                                ],
                                                "isError": false
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    },
                    "202": {
                        "description": "A notification was accepted. No body."
                    },
                    "401": {
                        "description": "No credential, or one that is expired or revoked. The `WWW-Authenticate` header points at the protected-resource document, which is what bootstraps the OAuth handshake.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32001,
                                        "message": "Authentication required.",
                                        "data": {
                                            "reason": "missing_token"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "The credential is valid but this server is out of reach \u2014 a capability that was not granted, a module switched off for the account, a suspended account, or a v3 API key used in place of an MCP credential. `data.reason` says which.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32002,
                                        "message": "This connection was not given access to Numbers. The account owner can add it by reconnecting.",
                                        "data": {
                                            "reason": "server_not_granted"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "No server by that key.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32002,
                                        "message": "No such MCP server.",
                                        "data": {
                                            "reason": "unknown_server"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "More than 120 requests in a minute from this connection.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32003,
                                        "message": "Too many MCP requests from this connection. Wait a minute and retry \u2014 do not loop."
                                    },
                                    "id": null
                                }
                            }
                        }
                    },
                    "503": {
                        "description": "The MCP surface is switched off platform-wide. Never cached \u2014 shutting it down is a database write that takes effect on the next request.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/JsonRpcResponse"
                                },
                                "example": {
                                    "jsonrpc": "2.0",
                                    "error": {
                                        "code": -32002,
                                        "message": "The MCP surface is not enabled on this platform right now.",
                                        "data": {
                                            "reason": "surface_disabled"
                                        }
                                    },
                                    "id": null
                                }
                            }
                        }
                    }
                }
            }
        },
        "/.well-known/oauth-authorization-server": {
            "get": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpOAuthAuthorizationServerMetadata",
                "summary": "OAuth 2.1 authorization server metadata",
                "description": "RFC 8414 discovery, and the **first** call a hosted client makes. Claude will not finish a connector setup without a `registration_endpoint` here, and ChatGPT's OAuth mode needs the same handshake.\n\n`scopes_supported` is the full granular set rather than a single blanket scope, because a client can only ask for what is advertised.",
                "x-generated-by": "php artisan mcp:manifest",
                "x-no-client-error": "A public discovery document with no request to get wrong: it is served unauthenticated, on any path suffix, and always answers 200.",
                "security": [],
                "responses": {
                    "200": {
                        "description": "The discovery document.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "issuer": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "The authorization server's identifier."
                                        },
                                        "authorization_endpoint": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Where the person is sent to approve the connection."
                                        },
                                        "token_endpoint": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "Where the authorization code is exchanged for a token."
                                        },
                                        "registration_endpoint": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "RFC 7591 dynamic client registration. Claude will not finish a connector setup without this field."
                                        },
                                        "response_types_supported": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "Only `code`."
                                        },
                                        "code_challenge_methods_supported": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "Only `S256`. PKCE is required, not optional."
                                        },
                                        "scopes_supported": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "enum": [
                                                    "mcp:use",
                                                    "mcp:overview",
                                                    "mcp:calls",
                                                    "mcp:routing",
                                                    "mcp:numbers",
                                                    "mcp:meetings",
                                                    "mcp:builders",
                                                    "mcp:data",
                                                    "mcp:studio",
                                                    "mcp:contacts",
                                                    "mcp:agents",
                                                    "mcp:commerce",
                                                    "mcp:support",
                                                    "mcp:accounts",
                                                    "mcp:approvals",
                                                    "mcp:payments",
                                                    "mcp:automations",
                                                    "mcp:alerts",
                                                    "mcp:operations",
                                                    "mcp:navigate",
                                                    "mcp:messaging",
                                                    "mcp:inbox",
                                                    "mcp:comments",
                                                    "mcp:posts",
                                                    "mcp:leads",
                                                    "mcp:groups",
                                                    "mcp:publish",
                                                    "mcp:send",
                                                    "mcp:spend",
                                                    "mcp:delete",
                                                    "mcp:write",
                                                    "mcp:shape",
                                                    "mcp:automate",
                                                    "mcp:approve"
                                                ]
                                            },
                                            "description": "Every scope a client may ask for. A client can only request what is advertised here."
                                        },
                                        "grant_types_supported": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "`authorization_code` and `refresh_token`."
                                        },
                                        "token_endpoint_auth_methods_supported": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "`none`: clients are public and authenticate with PKCE."
                                        }
                                    }
                                },
                                "example": {
                                    "issuer": "https://business.momo.tz",
                                    "authorization_endpoint": "https://business.momo.tz/oauth/authorize",
                                    "token_endpoint": "https://business.momo.tz/oauth/token",
                                    "registration_endpoint": "https://business.momo.tz/oauth/register",
                                    "response_types_supported": [
                                        "code"
                                    ],
                                    "code_challenge_methods_supported": [
                                        "S256"
                                    ],
                                    "scopes_supported": [
                                        "mcp:use",
                                        "mcp:overview",
                                        "mcp:calls",
                                        "mcp:routing",
                                        "mcp:numbers",
                                        "mcp:meetings",
                                        "mcp:builders",
                                        "mcp:data",
                                        "mcp:studio",
                                        "mcp:contacts",
                                        "mcp:agents",
                                        "mcp:commerce",
                                        "mcp:support",
                                        "mcp:accounts",
                                        "mcp:approvals",
                                        "mcp:payments",
                                        "mcp:automations",
                                        "mcp:alerts",
                                        "mcp:operations",
                                        "mcp:navigate",
                                        "mcp:messaging",
                                        "mcp:inbox",
                                        "mcp:comments",
                                        "mcp:posts",
                                        "mcp:leads",
                                        "mcp:groups",
                                        "mcp:publish",
                                        "mcp:send",
                                        "mcp:spend",
                                        "mcp:delete",
                                        "mcp:write",
                                        "mcp:shape",
                                        "mcp:automate",
                                        "mcp:approve"
                                    ],
                                    "grant_types_supported": [
                                        "authorization_code",
                                        "refresh_token"
                                    ],
                                    "token_endpoint_auth_methods_supported": [
                                        "none"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "/.well-known/oauth-protected-resource": {
            "get": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpOAuthProtectedResourceMetadata",
                "summary": "OAuth 2.1 protected resource metadata",
                "description": "RFC 9728. A client that gets a `401` from an MCP endpoint reads the `WWW-Authenticate` header, lands here, and learns which authorization server guards the resource. That chain is what turns an unauthenticated first request into a completed connector setup without anybody typing a URL.",
                "x-generated-by": "php artisan mcp:manifest",
                "x-no-client-error": "A public discovery document with no request to get wrong: it is served unauthenticated, on any path suffix, and always answers 200.",
                "security": [],
                "responses": {
                    "200": {
                        "description": "The resource metadata.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "resource": {
                                            "type": "string",
                                            "format": "uri",
                                            "description": "The protected resource this document describes."
                                        },
                                        "authorization_servers": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "format": "uri"
                                            },
                                            "description": "Where to go to get a token for it."
                                        },
                                        "scopes_supported": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "The base scope every MCP token carries."
                                        }
                                    }
                                },
                                "example": {
                                    "resource": "https://business.momo.tz",
                                    "authorization_servers": [
                                        "https://business.momo.tz"
                                    ],
                                    "scopes_supported": [
                                        "mcp:use"
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        },
        "/oauth/register": {
            "post": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpOAuthRegisterClient",
                "summary": "Register an OAuth client",
                "description": "RFC 7591 dynamic client registration. Open by design \u2014 a hosted client registers itself, unattended, the first time somebody adds the connector \u2014 which is why `redirect_uris` is checked against an allow-list of published callback hosts. Register a redirect you control and the authorization code for somebody's account would be delivered to you, so a redirect outside the list is rejected rather than trusted.\n\nThe issued client is public: no secret, PKCE required.",
                "x-generated-by": "php artisan mcp:manifest",
                "security": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "redirect_uris"
                                ],
                                "properties": {
                                    "client_name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "A name for the client. `name` is accepted as an alias; one of the two is required."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Alias for `client_name`."
                                    },
                                    "redirect_uris": {
                                        "type": "array",
                                        "minItems": 1,
                                        "items": {
                                            "type": "string",
                                            "format": "uri"
                                        },
                                        "description": "Absolute callback URLs. Each must sit under a permitted host, or under loopback for a desktop client that finishes the flow locally."
                                    }
                                }
                            },
                            "example": {
                                "client_name": "My agent",
                                "redirect_uris": [
                                    "https://claude.ai/api/mcp/auth_callback"
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The registered client.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "client_id": {
                                            "type": "string",
                                            "description": "Send this on the authorize and token calls."
                                        },
                                        "grant_types": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "The grants this client may use."
                                        },
                                        "response_types": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "Only `code`."
                                        },
                                        "redirect_uris": {
                                            "type": "array",
                                            "items": {
                                                "type": "string",
                                                "format": "uri"
                                            },
                                            "description": "The callbacks that were accepted."
                                        },
                                        "scope": {
                                            "type": "string",
                                            "description": "The default scope. Ask for more on the authorize call."
                                        },
                                        "token_endpoint_auth_method": {
                                            "type": "string",
                                            "const": "none",
                                            "description": "No client secret is issued: this is a public client and PKCE is the proof."
                                        }
                                    }
                                },
                                "example": {
                                    "client_id": "9d1f6c2a-4e1b-4a77-9a3a-0f2f1b0d5c11",
                                    "grant_types": [
                                        "authorization_code",
                                        "refresh_token"
                                    ],
                                    "response_types": [
                                        "code"
                                    ],
                                    "redirect_uris": [
                                        "https://claude.ai/api/mcp/auth_callback"
                                    ],
                                    "scope": "mcp:use",
                                    "token_endpoint_auth_method": "none"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "The registration was rejected \u2014 most often a redirect URI outside the permitted hosts.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "A sentence naming the first problem."
                                        },
                                        "errors": {
                                            "type": "object",
                                            "additionalProperties": {
                                                "type": "array",
                                                "items": {
                                                    "type": "string"
                                                }
                                            },
                                            "description": "Each rejected field mapped to its messages."
                                        }
                                    }
                                },
                                "example": {
                                    "message": "The redirect uris.0 field is not a permitted redirect domain.",
                                    "errors": {
                                        "redirect_uris.0": [
                                            "redirect_uris.0 is not a permitted redirect domain."
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "/oauth/token": {
            "post": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpOAuthIssueToken",
                "summary": "Exchange an authorization code for an access token",
                "description": "The standard OAuth 2.1 token endpoint, form-encoded. Public clients only: send `code_verifier`, not a client secret. `refresh_token` is supported with the same call and `grant_type=refresh_token`.\n\nThe returned token carries the scopes the account holder actually ticked, which may be fewer than the ones requested.",
                "x-generated-by": "php artisan mcp:manifest",
                "security": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/x-www-form-urlencoded": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "grant_type",
                                    "client_id"
                                ],
                                "properties": {
                                    "grant_type": {
                                        "type": "string",
                                        "enum": [
                                            "authorization_code",
                                            "refresh_token"
                                        ],
                                        "description": "Which exchange this is."
                                    },
                                    "client_id": {
                                        "type": "string",
                                        "description": "The client id from dynamic client registration."
                                    },
                                    "code": {
                                        "type": "string",
                                        "description": "The authorization code, for `grant_type=authorization_code`."
                                    },
                                    "redirect_uri": {
                                        "type": "string",
                                        "format": "uri",
                                        "description": "The same redirect used to obtain the code."
                                    },
                                    "code_verifier": {
                                        "type": "string",
                                        "description": "The PKCE verifier whose S256 challenge was sent to the authorize endpoint."
                                    },
                                    "refresh_token": {
                                        "type": "string",
                                        "description": "For `grant_type=refresh_token`."
                                    }
                                }
                            },
                            "example": {
                                "grant_type": "authorization_code",
                                "client_id": "9d1f6c2a-4e1b-4a77-9a3a-0f2f1b0d5c11",
                                "code": "def502009a\u2026",
                                "redirect_uri": "https://claude.ai/api/mcp/auth_callback",
                                "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "The access token.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "token_type": {
                                            "type": "string",
                                            "const": "Bearer",
                                            "description": "Always \"Bearer\"."
                                        },
                                        "expires_in": {
                                            "type": "integer",
                                            "description": "Seconds until the access token expires."
                                        },
                                        "access_token": {
                                            "type": "string",
                                            "description": "Send as `Authorization: Bearer \u2026` on the MCP endpoints."
                                        },
                                        "refresh_token": {
                                            "type": "string",
                                            "description": "Exchange this for a new access token with `grant_type=refresh_token`."
                                        },
                                        "scope": {
                                            "type": "string",
                                            "description": "Space-separated scopes actually granted, which may be fewer than were asked for."
                                        }
                                    }
                                },
                                "example": {
                                    "token_type": "Bearer",
                                    "expires_in": 31536000,
                                    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9\u2026",
                                    "refresh_token": "def50200f0a1\u2026",
                                    "scope": "mcp:use mcp:overview mcp:calls"
                                }
                            }
                        }
                    },
                    "400": {
                        "description": "The grant was refused \u2014 a spent or mismatched code, a bad `code_verifier`, or an unknown client.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "error": {
                                            "type": "string",
                                            "description": "The OAuth error code, such as `invalid_grant` or `invalid_client`."
                                        },
                                        "error_description": {
                                            "type": "string",
                                            "description": "What went wrong, in a sentence."
                                        },
                                        "hint": {
                                            "type": "string",
                                            "description": "Which part of the request was at fault, when the server can tell."
                                        },
                                        "message": {
                                            "type": "string",
                                            "description": "The same text as `error_description`."
                                        }
                                    }
                                },
                                "example": {
                                    "error": "invalid_grant",
                                    "error_description": "The provided authorization grant is invalid, expired, revoked, or was issued to another client.",
                                    "message": "The provided authorization grant is invalid, expired, revoked, or was issued to another client."
                                }
                            }
                        }
                    },
                    "429": {
                        "description": "Too many token requests. Back off and retry.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "message": {
                                            "type": "string",
                                            "description": "The refusal, in a sentence."
                                        }
                                    }
                                },
                                "example": {
                                    "message": "Too Many Attempts."
                                }
                            }
                        }
                    }
                }
            }
        },
        "/api-docs/mcp.json": {
            "get": {
                "tags": [
                    "MCP"
                ],
                "operationId": "mcpToolManifest",
                "summary": "Get the MCP tool manifest",
                "description": "The machine-readable tool contract: every server, every tool, and a **complete JSON Schema** for each tool's arguments \u2014 generate typed bindings from it rather than hand-writing them.\n\nPublic and unauthenticated on purpose, so a developer can point a client at us before they have signed up. It is the same document this OpenAPI file is for REST: this one describes the transport, that one describes the operations.",
                "x-generated-by": "php artisan mcp:manifest",
                "x-no-client-error": "A public document, served to anyone with no parameters to get wrong.",
                "security": [],
                "responses": {
                    "200": {
                        "description": "The manifest.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "generated_by": {
                                            "type": "string",
                                            "const": "php artisan mcp:manifest",
                                            "description": "The command that wrote this document. It is generated, never hand-edited."
                                        },
                                        "transport": {
                                            "type": "string",
                                            "const": "streamable-http",
                                            "description": "The MCP transport every server speaks."
                                        },
                                        "protocol_versions": {
                                            "type": "array",
                                            "items": {
                                                "type": "string"
                                            },
                                            "description": "Protocol versions accepted at `initialize`, newest first."
                                        },
                                        "auth": {
                                            "type": "object",
                                            "description": "The OAuth handshake and the bearer alternative, plus the scopes a consent screen offers.",
                                            "additionalProperties": true
                                        },
                                        "presets": {
                                            "type": "array",
                                            "items": {
                                                "type": "object",
                                                "additionalProperties": true
                                            },
                                            "description": "Ready-made server selections offered when somebody creates a connection."
                                        },
                                        "server_count": {
                                            "type": "integer",
                                            "description": "How many servers are mounted."
                                        },
                                        "tool_count": {
                                            "type": "integer",
                                            "description": "How many tools they carry between them."
                                        },
                                        "root": {
                                            "type": "object",
                                            "description": "The aggregate root at `/mcp` \u2014 every area a connection was granted, behind one URL.",
                                            "properties": {
                                                "path": {
                                                    "type": "string",
                                                    "description": "The endpoint, relative to the API host."
                                                },
                                                "tool_count": {
                                                    "type": "integer",
                                                    "description": "How many distinct tools the whole surface carries."
                                                },
                                                "tools_hash": {
                                                    "type": "string",
                                                    "description": "One hash over every tool's version. Store it, and a single comparison tells you whether the surface you generated against is the one being served.",
                                                    "examples": [
                                                        "a1b2c3d4"
                                                    ]
                                                }
                                            },
                                            "additionalProperties": true
                                        },
                                        "servers": {
                                            "type": "array",
                                            "description": "Every server and the tools it carries.",
                                            "items": {
                                                "type": "object",
                                                "properties": {
                                                    "key": {
                                                        "type": "string",
                                                        "description": "The `{server}` path segment."
                                                    },
                                                    "name": {
                                                        "type": "string",
                                                        "description": "Display name."
                                                    },
                                                    "summary": {
                                                        "type": "string",
                                                        "description": "What the server is for."
                                                    },
                                                    "path": {
                                                        "type": "string",
                                                        "description": "The endpoint, relative to the API host."
                                                    },
                                                    "module": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "description": "The sidebar module this server follows; null when it is always available."
                                                    },
                                                    "instructions": {
                                                        "type": "string",
                                                        "description": "What the server tells a model about itself at `initialize`."
                                                    },
                                                    "tools": {
                                                        "type": "array",
                                                        "items": {
                                                            "$ref": "#/components/schemas/ToolDefinition"
                                                        },
                                                        "description": "Its tools, each with a full JSON Schema for its arguments."
                                                    }
                                                }
                                            }
                                        }
                                    }
                                },
                                "example": {
                                    "generated_by": "php artisan mcp:manifest",
                                    "transport": "streamable-http",
                                    "protocol_versions": [
                                        "2025-11-25",
                                        "2025-06-18",
                                        "2025-03-26"
                                    ],
                                    "server_count": 21,
                                    "tool_count": 104,
                                    "servers": [
                                        {
                                            "key": "ivr",
                                            "name": "IVR",
                                            "path": "/mcp/v1/ivr",
                                            "tools": [
                                                {
                                                    "name": "list_ivr_flows",
                                                    "version": "3f9c1a04",
                                                    "description": "The call flows on this account, newest first.",
                                                    "writes": false,
                                                    "permissions": [
                                                        "ivr.view"
                                                    ],
                                                    "input_schema": {
                                                        "$schema": "https://json-schema.org/draft/2020-12/schema",
                                                        "title": "list_ivr_flows arguments",
                                                        "type": "object",
                                                        "properties": {
                                                            "search": {
                                                                "type": "string",
                                                                "description": "Filter by name."
                                                            }
                                                        }
                                                    }
                                                }
                                            ]
                                        }
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "webhooks": {
        "messageEvent": {
            "post": {
                "tags": [
                    "Webhooks"
                ],
                "operationId": "webhookMessageEvent",
                "summary": "Every event we POST to your server",
                "description": "A signed JSON POST to each receiver you registered for the event. Every delivery is a record you can read back at `GET /api/v3/webhooks/{webhook}/deliveries` and replay. **Retries:** a 5xx, a 408/425/429, a timeout or a connection failure is retried five times over about six hours (1 m, 5 m, 30 m, 2 h, 6 h) \u2014 six attempts in all. Any other 4xx is treated as \"understood and refused\" and is not retried. After fifty consecutive failures the endpoint is paused and the people who manage webhooks are told; replaying any failed delivery resumes it. **Dedupe on `event_id`** (also `X-Event-Id`): it is the same on every retry, every replay and every endpoint. **Answer 2xx quickly** \u2014 persist or enqueue, then acknowledge \u2014 and verify the signature over the raw bytes before parsing.",
                "security": [],
                "parameters": [
                    {
                        "name": "X-Signature",
                        "in": "header",
                        "required": true,
                        "description": "Plain hex HMAC-SHA256 of the raw body under the endpoint secret; no prefix. Unchanged from the first version, so existing receivers keep verifying.",
                        "schema": {
                            "type": "string",
                            "pattern": "^[a-f0-9]{64}$"
                        },
                        "example": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                    },
                    {
                        "name": "X-Signature-V2",
                        "in": "header",
                        "required": true,
                        "description": "Prefer this. `sha256=` + hex HMAC-SHA256 of `\"{X-Timestamp}.{X-Delivery-Id}.{raw body}\"` under the endpoint secret. Checking it gives you replay protection for free: refuse a timestamp older than five minutes, and remember delivery ids you have seen.",
                        "schema": {
                            "type": "string",
                            "pattern": "^sha256=[a-f0-9]{64}$"
                        },
                        "example": "sha256=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
                    },
                    {
                        "name": "X-Timestamp",
                        "in": "header",
                        "required": true,
                        "description": "Unix seconds when this attempt was sent. Part of the V2 signature.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "1757581442"
                    },
                    {
                        "name": "X-Delivery-Id",
                        "in": "header",
                        "required": true,
                        "description": "This delivery's id, the same across the automatic retries of it and part of the V2 signature. A manual replay gets a new one \u2014 dedupe on `X-Event-Id` instead.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "dlv_01j9qk3v8x2m7n4p5r6s"
                    },
                    {
                        "name": "X-Event",
                        "in": "header",
                        "required": true,
                        "description": "The event name, so a receiver can route before parsing.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "order.received"
                    },
                    {
                        "name": "X-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "The event's id (`evt_` + ULID), equal to `event_id` in the body. Stable across retries, replays and endpoints: this is what to dedupe on.",
                        "schema": {
                            "type": "string",
                            "pattern": "^evt_[0-9A-Z]{26}$"
                        },
                        "example": "evt_01J8Z6Q4M3T8W5K2N7XQ4R9ABC"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "description": "The event payload.",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookEvent"
                            },
                            "examples": {
                                "message_received": {
                                    "summary": "A message arrived",
                                    "value": {
                                        "event": "message.received",
                                        "message_id": 101,
                                        "direction": "inbound",
                                        "sender": "255712345678",
                                        "recipient": "MyBrand",
                                        "status": "received",
                                        "body": "Habari, mna kanga?",
                                        "media_url": null,
                                        "channel_type": "whatsapp",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "message_sent": {
                                    "summary": "A message was sent",
                                    "value": {
                                        "event": "message.sent",
                                        "message_id": 102,
                                        "direction": "outbound",
                                        "sender": "MyBrand",
                                        "recipient": "255712345678",
                                        "status": "sent",
                                        "body": "Ndiyo, tuna kanga.",
                                        "media_url": null,
                                        "channel_type": "whatsapp",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "message_delivered": {
                                    "summary": "A message was delivered",
                                    "value": {
                                        "event": "message.delivered",
                                        "message_id": 102,
                                        "direction": "outbound",
                                        "sender": "MyBrand",
                                        "recipient": "255712345678",
                                        "status": "delivered",
                                        "body": "Ndiyo, tuna kanga.",
                                        "media_url": null,
                                        "channel_type": "whatsapp",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "message_read": {
                                    "summary": "A message was read",
                                    "value": {
                                        "event": "message.read",
                                        "message_id": 102,
                                        "direction": "outbound",
                                        "sender": "MyBrand",
                                        "recipient": "255712345678",
                                        "status": "read",
                                        "body": "Ndiyo, tuna kanga.",
                                        "media_url": null,
                                        "channel_type": "whatsapp",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "message_failed": {
                                    "summary": "A message failed",
                                    "value": {
                                        "event": "message.failed",
                                        "message_id": 103,
                                        "direction": "outbound",
                                        "sender": "MyBrand",
                                        "recipient": "255712345678",
                                        "status": "failed",
                                        "body": "Ofa ya leo!",
                                        "media_url": null,
                                        "channel_type": "sms",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "message_echoed": {
                                    "summary": "A message was sent from the phone itself",
                                    "value": {
                                        "event": "message.echoed",
                                        "message_id": 104,
                                        "direction": "outbound",
                                        "sender": "MyBrand",
                                        "recipient": "255712345678",
                                        "status": "sent",
                                        "body": "Karibu!",
                                        "media_url": null,
                                        "channel_type": "whatsapp",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "message_updated": {
                                    "summary": "A message was edited",
                                    "value": {
                                        "event": "message.updated",
                                        "message_id": 101,
                                        "direction": "inbound",
                                        "sender": "255712345678",
                                        "recipient": "MyBrand",
                                        "status": "received",
                                        "body": "Habari, mna kanga za bluu?",
                                        "media_url": null,
                                        "channel_type": "whatsapp",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "order_received": {
                                    "summary": "An order arrived",
                                    "value": {
                                        "event": "order.received",
                                        "order": {
                                            "id": 9182,
                                            "catalogue_id": 42,
                                            "platform": "whatsapp",
                                            "status": "pending",
                                            "needs_attention": false,
                                            "stock_policy": "external",
                                            "customer_handle": "255712345678",
                                            "customer_name": "Asha Mrisho",
                                            "customer_phone": "255712345678",
                                            "customer_note": null,
                                            "lines": [
                                                {
                                                    "sku": "MNG-45W",
                                                    "name": "Charger Mango 45W",
                                                    "quantity": 1,
                                                    "unit_price_minor": 3900000,
                                                    "line_total_minor": 3900000,
                                                    "currency": "TZS",
                                                    "reserved": 1,
                                                    "stock_short": false,
                                                    "unresolved": false
                                                }
                                            ],
                                            "total_minor": 3900000,
                                            "currency": "TZS",
                                            "conversation_id": 771,
                                            "priced_at": "2026-09-11T09:14:02+00:00",
                                            "created_at": "2026-09-11T09:14:02+00:00",
                                            "order_id": 9182,
                                            "customer_wa_id": "255712345678",
                                            "total_amount": 3900000,
                                            "total_currency": "TZS"
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "order_status_changed": {
                                    "summary": "An order changed status",
                                    "value": {
                                        "event": "order.status_changed",
                                        "order": {
                                            "id": 9182,
                                            "catalogue_id": 42,
                                            "platform": "whatsapp",
                                            "status": "confirmed",
                                            "needs_attention": false,
                                            "stock_policy": "external",
                                            "customer_handle": "255712345678",
                                            "customer_name": "Asha Mrisho",
                                            "customer_phone": "255712345678",
                                            "customer_note": null,
                                            "lines": [
                                                {
                                                    "sku": "MNG-45W",
                                                    "name": "Charger Mango 45W",
                                                    "quantity": 1,
                                                    "unit_price_minor": 3900000,
                                                    "line_total_minor": 3900000,
                                                    "currency": "TZS",
                                                    "reserved": 1,
                                                    "stock_short": false,
                                                    "unresolved": false
                                                }
                                            ],
                                            "total_minor": 3900000,
                                            "currency": "TZS",
                                            "conversation_id": 771,
                                            "priced_at": "2026-09-11T09:14:02+00:00",
                                            "created_at": "2026-09-11T09:14:02+00:00",
                                            "order_id": 9182,
                                            "customer_wa_id": "255712345678",
                                            "total_amount": 3900000,
                                            "total_currency": "TZS"
                                        },
                                        "previous_status": "pending",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "order_cancelled": {
                                    "summary": "An order was cancelled",
                                    "value": {
                                        "event": "order.cancelled",
                                        "order": {
                                            "id": 9182,
                                            "catalogue_id": 42,
                                            "platform": "whatsapp",
                                            "status": "cancelled",
                                            "needs_attention": false,
                                            "stock_policy": "external",
                                            "customer_handle": "255712345678",
                                            "customer_name": "Asha Mrisho",
                                            "customer_phone": "255712345678",
                                            "customer_note": null,
                                            "lines": [
                                                {
                                                    "sku": "MNG-45W",
                                                    "name": "Charger Mango 45W",
                                                    "quantity": 1,
                                                    "unit_price_minor": 3900000,
                                                    "line_total_minor": 3900000,
                                                    "currency": "TZS",
                                                    "reserved": 1,
                                                    "stock_short": false,
                                                    "unresolved": false
                                                }
                                            ],
                                            "total_minor": 3900000,
                                            "currency": "TZS",
                                            "conversation_id": 771,
                                            "priced_at": "2026-09-11T09:14:02+00:00",
                                            "created_at": "2026-09-11T09:14:02+00:00",
                                            "order_id": 9182,
                                            "customer_wa_id": "255712345678",
                                            "total_amount": 3900000,
                                            "total_currency": "TZS"
                                        },
                                        "previous_status": "pending",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "order_paid": {
                                    "summary": "An order was paid",
                                    "value": {
                                        "event": "order.paid",
                                        "order_id": 9182,
                                        "payment_id": 4410,
                                        "method": "ussd_push",
                                        "amount_minor": 3900000,
                                        "currency": "TZS",
                                        "payer_msisdn": "255712345678",
                                        "paid_at": "2026-09-11T09:14:02+00:00",
                                        "conversation_id": 771,
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "sync_completed": {
                                    "summary": "A bulk sync finished",
                                    "value": {
                                        "event": "sync.completed",
                                        "sync": {
                                            "id": 812,
                                            "catalogue_id": 42,
                                            "source": "api",
                                            "mode": "upsert",
                                            "status": "completed",
                                            "received": 2000,
                                            "created": 12,
                                            "updated": 1982,
                                            "unchanged": 0,
                                            "rejected": 6,
                                            "retired": 0,
                                            "platforms": {
                                                "whatsapp": {
                                                    "synced": 1960,
                                                    "blocked": 34
                                                }
                                            },
                                            "problems_truncated": false
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "stock_low": {
                                    "summary": "A product is running low",
                                    "value": {
                                        "event": "stock.low",
                                        "catalogue_id": 42,
                                        "sku": "MNG-45W",
                                        "name": "Charger Mango 45W",
                                        "available": 2,
                                        "threshold": 3,
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "product_blocked": {
                                    "summary": "A platform will not show a product",
                                    "value": {
                                        "event": "product.blocked",
                                        "catalogue_id": 42,
                                        "sku": "MNG-KNIFE",
                                        "platform": "whatsapp",
                                        "problem": "WhatsApp needs a product image it can fetch.",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "product_drifted": {
                                    "summary": "A platform's copy of a product differs from ours",
                                    "value": {
                                        "event": "product.drifted",
                                        "catalogue_id": 42,
                                        "sku": "MNG-45W",
                                        "platform": "whatsapp",
                                        "source_of_truth": "api",
                                        "diff": {
                                            "price": {
                                                "ours": 4500000,
                                                "theirs": 4200000
                                            }
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "campaign_completed": {
                                    "summary": "A campaign finished",
                                    "value": {
                                        "event": "campaign.completed",
                                        "campaign_uid": "cmp_8f2c",
                                        "sent": 1180,
                                        "failed": 20,
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "campaign_failed": {
                                    "summary": "A campaign failed",
                                    "value": {
                                        "event": "campaign.failed",
                                        "campaign_uid": "cmp_8f2c",
                                        "reason": "Insufficient balance.",
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_created": {
                                    "summary": "A group was created",
                                    "value": {
                                        "event": "group.created",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_create_failed": {
                                    "summary": "A group could not be created",
                                    "value": {
                                        "event": "group.create_failed",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_updated": {
                                    "summary": "A group was updated",
                                    "value": {
                                        "event": "group.updated",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_deleted": {
                                    "summary": "A group was deleted",
                                    "value": {
                                        "event": "group.deleted",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_suspended": {
                                    "summary": "A group was suspended by WhatsApp",
                                    "value": {
                                        "event": "group.suspended",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_suspension_cleared": {
                                    "summary": "A group suspension was lifted",
                                    "value": {
                                        "event": "group.suspension_cleared",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_participant_joined": {
                                    "summary": "Someone joined a group",
                                    "value": {
                                        "event": "group.participant_joined",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_participant_left": {
                                    "summary": "Someone left a group",
                                    "value": {
                                        "event": "group.participant_left",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_participant_removed": {
                                    "summary": "Someone was removed from a group",
                                    "value": {
                                        "event": "group.participant_removed",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_join_requested": {
                                    "summary": "Someone asked to join a group",
                                    "value": {
                                        "event": "group.join_requested",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_join_request_revoked": {
                                    "summary": "A join request was withdrawn",
                                    "value": {
                                        "event": "group.join_request_revoked",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "group_invite_sent": {
                                    "summary": "A group invite was sent",
                                    "value": {
                                        "event": "group.invite_sent",
                                        "group": {
                                            "id": 31,
                                            "subject": "Wateja wa Dar",
                                            "participants_count": 48
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "webhook_paused": {
                                    "summary": "An endpoint was paused",
                                    "value": {
                                        "event": "webhook.paused",
                                        "webhook_id": 7,
                                        "url": "https://store.example.com/momo",
                                        "consecutive_failures": 50,
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "flow_session_started": {
                                    "summary": "A flow session started",
                                    "value": {
                                        "event": "flow.session.started",
                                        "session_id": 5120,
                                        "flow_id": 17,
                                        "flow_name": "Oda ya chakula",
                                        "flow_version": 3,
                                        "conversation_id": 771,
                                        "contact_id": 2201,
                                        "contact_name": "Asha Mrisho",
                                        "contact_identifier": "255712345678",
                                        "trigger": "inbound",
                                        "status": "running",
                                        "outcome": "in_progress",
                                        "ended_reason": null,
                                        "node_id": "ask_name",
                                        "turns": 0,
                                        "started_at": "2026-09-11T09:14:02+00:00",
                                        "ended_at": null,
                                        "variables": [],
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "flow_session_ended": {
                                    "summary": "A flow session ended",
                                    "value": {
                                        "event": "flow.session.ended",
                                        "session_id": 5120,
                                        "flow_id": 17,
                                        "flow_name": "Oda ya chakula",
                                        "flow_version": 3,
                                        "conversation_id": 771,
                                        "contact_id": 2201,
                                        "contact_name": "Asha Mrisho",
                                        "contact_identifier": "255712345678",
                                        "trigger": "inbound",
                                        "status": "completed",
                                        "outcome": "completed",
                                        "ended_reason": "completed",
                                        "node_id": "done",
                                        "turns": 6,
                                        "started_at": "2026-09-11T09:14:02+00:00",
                                        "ended_at": "2026-09-11T09:14:02+00:00",
                                        "variables": {
                                            "order_ref": "ORD-2026-0091",
                                            "total": 24000
                                        },
                                        "timestamp": "2026-09-11T09:14:02+00:00"
                                    }
                                },
                                "lead_stage_changed": {
                                    "summary": "A lead moved stage",
                                    "value": {
                                        "event": "lead.stage_changed",
                                        "event_id": "evt_01J8Z6Q4M3T8W5K2N7XQ4R9ABC",
                                        "timestamp": "2026-09-25T14:03:11+03:00",
                                        "lead": {
                                            "id": "0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20",
                                            "name": "Amina Juma",
                                            "phone": "+255712345678",
                                            "email": null,
                                            "company": "Amina Shop",
                                            "location": "Mbezi, Dar es Salaam",
                                            "stage": "qualified",
                                            "closed_at": null,
                                            "archived_at": null,
                                            "lost_reason": null,
                                            "source_channel": "whatsapp",
                                            "source_detail": "Ad: October solar promo",
                                            "interest": "Solar kit 5 kW",
                                            "estimated_value": 4500000,
                                            "currency": "TZS",
                                            "score": 72,
                                            "score_reason": "Budget stated, wants install this month",
                                            "summary": "Shop owner in Mbezi who needs backup power for two fridges. Budget about TSh 4.5M.",
                                            "next_action": "Send quote",
                                            "next_action_at": "2026-09-26T10:00:00+03:00",
                                            "labels": [
                                                "hot",
                                                "follow-up"
                                            ],
                                            "assigned_to": {
                                                "id": 311,
                                                "name": "Baraka M."
                                            },
                                            "custom_fields": {
                                                "budget_band": "mid"
                                            },
                                            "created_by": {
                                                "kind": "ai",
                                                "id": 14
                                            },
                                            "created_at": "2026-09-24T09:12:40+03:00",
                                            "updated_at": "2026-09-25T14:03:11+03:00",
                                            "url": "https://business.momo.tz/app/leads/0199a2c4-6f1e-7c1a-9d2b-3c5e8f7a1b20"
                                        },
                                        "changes": {
                                            "stage": {
                                                "from": "contacted",
                                                "to": "qualified"
                                            }
                                        },
                                        "reason": null,
                                        "actor": {
                                            "kind": "ai",
                                            "id": 14,
                                            "label": "Mauzo AI"
                                        },
                                        "source": {
                                            "kind": "conversation",
                                            "id": "88213",
                                            "channel": "whatsapp"
                                        }
                                    }
                                },
                                "call_completed": {
                                    "summary": "A campaign or API call ended",
                                    "value": {
                                        "event": "call.completed",
                                        "event_id": "evt_call_completed_81234",
                                        "call": {
                                            "id": 81234,
                                            "room_name": "out-7f3c2a",
                                            "direction": "outbound",
                                            "status": "ended",
                                            "outcome": "answered",
                                            "answered": true,
                                            "from": "+255746000111",
                                            "to": "+255712345678",
                                            "mode": "message",
                                            "agent_config_id": null,
                                            "source": "api",
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "answered_at": "2026-10-07T10:00:07+03:00",
                                            "ended_at": "2026-10-07T10:00:31+03:00",
                                            "duration_seconds": 24,
                                            "sip_status_code": null,
                                            "keys_pressed": [
                                                {
                                                    "digit": "1",
                                                    "action": "confirm",
                                                    "label": "Thibitisha",
                                                    "at": "2026-10-07T07:00:21Z"
                                                }
                                            ],
                                            "recording_available": false,
                                            "transcript_available": false,
                                            "request": {
                                                "external_ref": "order-A1023",
                                                "purpose": null,
                                                "variables": {
                                                    "jina": "Amina",
                                                    "oda": "A1023"
                                                },
                                                "estimated_cost": 87
                                            },
                                            "campaign": null
                                        },
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_recording_ready": {
                                    "summary": "A call recording is ready",
                                    "value": {
                                        "event": "call.recording_ready",
                                        "event_id": "evt_call_recording_81234_77",
                                        "call": {
                                            "id": 81234,
                                            "room_name": "out-7f3c2a",
                                            "direction": "outbound",
                                            "status": "ended",
                                            "outcome": "answered",
                                            "answered": true,
                                            "from": "+255746000111",
                                            "to": "+255712345678",
                                            "mode": "message",
                                            "agent_config_id": null,
                                            "source": "api",
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "answered_at": "2026-10-07T10:00:07+03:00",
                                            "ended_at": "2026-10-07T10:00:31+03:00",
                                            "duration_seconds": 24,
                                            "sip_status_code": null,
                                            "keys_pressed": [
                                                {
                                                    "digit": "1",
                                                    "action": "confirm",
                                                    "label": "Thibitisha",
                                                    "at": "2026-10-07T07:00:21Z"
                                                }
                                            ],
                                            "recording_available": false,
                                            "transcript_available": false,
                                            "request": {
                                                "external_ref": "order-A1023",
                                                "purpose": null,
                                                "variables": {
                                                    "jina": "Amina",
                                                    "oda": "A1023"
                                                },
                                                "estimated_cost": 87
                                            },
                                            "campaign": null
                                        },
                                        "recording": {
                                            "id": 77,
                                            "duration_seconds": 24,
                                            "status": "complete",
                                            "list_url": "https://business.momo.tz/api/v3/calls/81234/recordings"
                                        },
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_feedback_ready": {
                                    "summary": "An AI call summary is ready",
                                    "value": {
                                        "event": "call.feedback_ready",
                                        "event_id": "evt_call_feedback_81234",
                                        "call": {
                                            "id": 81234,
                                            "room_name": "out-7f3c2a",
                                            "direction": "outbound",
                                            "status": "ended",
                                            "outcome": "answered",
                                            "answered": true,
                                            "from": "+255746000111",
                                            "to": "+255712345678",
                                            "mode": "ai",
                                            "agent_config_id": null,
                                            "source": "api",
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "answered_at": "2026-10-07T10:00:07+03:00",
                                            "ended_at": "2026-10-07T10:00:31+03:00",
                                            "duration_seconds": 24,
                                            "sip_status_code": null,
                                            "keys_pressed": [
                                                {
                                                    "digit": "1",
                                                    "action": "confirm",
                                                    "label": "Thibitisha",
                                                    "at": "2026-10-07T07:00:21Z"
                                                }
                                            ],
                                            "recording_available": false,
                                            "transcript_available": false,
                                            "request": {
                                                "external_ref": "order-A1023",
                                                "purpose": null,
                                                "variables": {
                                                    "jina": "Amina",
                                                    "oda": "A1023"
                                                },
                                                "estimated_cost": 87
                                            },
                                            "campaign": null
                                        },
                                        "feedback": {
                                            "summary": "Amina confirmed and wants delivery after 17:00.",
                                            "sentiment": "positive",
                                            "disposition": "confirmed",
                                            "key_topics": [
                                                "delivery time"
                                            ],
                                            "action_items": [
                                                "Deliver after 17:00"
                                            ],
                                            "next_best_action": null
                                        },
                                        "answers": {
                                            "confirmed": true
                                        },
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_campaign_started": {
                                    "summary": "A call campaign started calling",
                                    "value": {
                                        "event": "call_campaign.started",
                                        "event_id": "evt_ccev_901",
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "running",
                                            "state": "calling",
                                            "state_label": "Calling",
                                            "needs_attention": false,
                                            "pause_reason": null,
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": null,
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        },
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_campaign_target_completed": {
                                    "summary": "A person's calls are done",
                                    "value": {
                                        "event": "call_campaign.target_completed",
                                        "event_id": "evt_cctg_5501_3f9a1c2b7d",
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "external_ref": "cod-confirmations",
                                            "is_rolling": true
                                        },
                                        "target": {
                                            "id": 5501,
                                            "position": 87,
                                            "to": "+255712345678",
                                            "name": "Amina J.",
                                            "external_id": "order-A1023",
                                            "contact_id": null,
                                            "result": "pressed",
                                            "result_label": "Pressed 1",
                                            "final": true,
                                            "tries": 1,
                                            "max_tries": 3,
                                            "next_try_at": null,
                                            "keys_pressed": [
                                                "1"
                                            ],
                                            "answers": {
                                                "confirmed": true
                                            },
                                            "summary": null,
                                            "variables": {
                                                "jina": "Amina J.",
                                                "oda": "A1023",
                                                "kiasi": "45,000"
                                            },
                                            "last_call_id": 81234,
                                            "last_call_at": "2026-10-07T10:00:00+03:00",
                                            "cost": 87,
                                            "created_at": "2026-10-07T10:00:00+03:00"
                                        },
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_campaign_paused": {
                                    "summary": "A call campaign paused",
                                    "value": {
                                        "event": "call_campaign.paused",
                                        "event_id": "evt_ccev_902",
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "paused",
                                            "state": "paused",
                                            "state_label": "Paused",
                                            "needs_attention": false,
                                            "pause_reason": "wallet_low",
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": null,
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        },
                                        "reason": "wallet_low",
                                        "automatic": true,
                                        "top_up": 6000,
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_campaign_resumed": {
                                    "summary": "A call campaign resumed",
                                    "value": {
                                        "event": "call_campaign.resumed",
                                        "event_id": "evt_ccev_903",
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "running",
                                            "state": "calling",
                                            "state_label": "Calling",
                                            "needs_attention": false,
                                            "pause_reason": null,
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": null,
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        },
                                        "automatic": true,
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_campaign_completed": {
                                    "summary": "A call campaign ended",
                                    "value": {
                                        "event": "call_campaign.completed",
                                        "event_id": "evt_ccev_904",
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "cancelled",
                                            "state": "stopped",
                                            "state_label": "Stopped",
                                            "needs_attention": false,
                                            "pause_reason": null,
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": "2026-10-07T10:00:00+03:00",
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        },
                                        "state": "stopped",
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "call_campaign_failed": {
                                    "summary": "A call campaign could not run",
                                    "value": {
                                        "event": "call_campaign.failed",
                                        "event_id": "evt_ccev_905",
                                        "campaign": {
                                            "id": "01928c3e-7a1b-7c2d-9e0f-123456789abc",
                                            "name": "Confirm orders",
                                            "goal": "confirm_orders",
                                            "status": "failed",
                                            "state": "finished",
                                            "state_label": "Finished",
                                            "needs_attention": false,
                                            "pause_reason": null,
                                            "attention_reason": null,
                                            "mode": "message",
                                            "is_rolling": true,
                                            "purpose_class": "transactional",
                                            "source": "api",
                                            "external_ref": "cod-confirmations",
                                            "people": 120,
                                            "counts": {
                                                "all": 120,
                                                "waiting": 14,
                                                "calling": 2,
                                                "reached": 31,
                                                "pressed": 58,
                                                "pressed_by_digit": {
                                                    "1": 51,
                                                    "2": 7
                                                },
                                                "reached_total": 89,
                                                "callback": 0,
                                                "not_reached": 15,
                                                "opted_out": 0,
                                                "wrong_number": 0,
                                                "skipped": 0
                                            },
                                            "spent": 7743,
                                            "held": 2088,
                                            "likely_cost": 6264,
                                            "currency": "TZS",
                                            "message": {
                                                "text": "Habari {jina}, tunathibitisha oda yako {oda} ya shilingi {kiasi}. Bonyeza 1 kuthibitisha, 2 kuighairi. Bonyeza 9 tusikupigie tena.",
                                                "audio_asset_id": null,
                                                "voice_id": null,
                                                "voice_model": null,
                                                "language": "sw",
                                                "repeat": 1
                                            },
                                            "keys": {
                                                "1": {
                                                    "action": "confirm",
                                                    "label": "Thibitisha"
                                                },
                                                "2": {
                                                    "action": "tag",
                                                    "label": "Ghairi",
                                                    "tag": "cancelled_order"
                                                },
                                                "9": {
                                                    "action": "opt_out",
                                                    "label": "Usipigiwe tena / Stop calling me"
                                                }
                                            },
                                            "ivr_flow_id": null,
                                            "agent_config_id": null,
                                            "answer_fields": [],
                                            "settings": {
                                                "calling_window": {
                                                    "timezone": "Africa/Dar_es_Salaam",
                                                    "days": [
                                                        1,
                                                        2,
                                                        3,
                                                        4,
                                                        5,
                                                        6
                                                    ],
                                                    "from": "08:00",
                                                    "to": "20:00",
                                                    "enforced": true
                                                },
                                                "max_tries": 3,
                                                "ring_seconds": 30,
                                                "lines": null,
                                                "from_number": null,
                                                "stop_rule": "call_everyone",
                                                "max_call_seconds": 90,
                                                "record_calls": false,
                                                "cooldown_hours": 0,
                                                "budget_cap": null
                                            },
                                            "connections": {
                                                "leads": {
                                                    "answer_key": "interested",
                                                    "stage": "qualified",
                                                    "note": true
                                                }
                                            },
                                            "scheduled_at": null,
                                            "started_at": "2026-10-07T10:00:00+03:00",
                                            "paused_at": null,
                                            "finished_at": null,
                                            "created_at": "2026-10-07T10:00:00+03:00",
                                            "updated_at": "2026-10-07T10:00:00+03:00"
                                        },
                                        "reason": "client_not_found",
                                        "timestamp": "2026-10-07T10:00:00+03:00"
                                    }
                                },
                                "webhook_test": {
                                    "summary": "The Test button",
                                    "value": {
                                        "event": "webhook.test",
                                        "event_id": "evt_01J8Z7A0B1C2D3E4F5G6H7J8KM",
                                        "timestamp": "2026-09-25T14:03:11+03:00",
                                        "test": true,
                                        "message": "A test from Momo Business. Answer 2xx and this endpoint is working."
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Your receiver acknowledged the event. The current dispatcher does not retry based on receiver status or parse its response body.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "properties": {
                                        "received": {
                                            "type": "boolean",
                                            "description": "Illustrative acknowledgement chosen by your receiver."
                                        }
                                    }
                                },
                                "examples": {
                                    "default": {
                                        "value": {
                                            "received": true
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        "businessEvent": {
            "post": {
                "operationId": "receiveBusinessEvent",
                "tags": [
                    "Webhooks"
                ],
                "summary": "Receive a signed automation business event",
                "description": "Sent to the URL of a webhook event subscription. This is a different protocol from messageEvent communication callbacks. Verify X-Momo-Signature over timestamp + dot + raw body; the helper default timestamp tolerance is 300 seconds. The payload is serialized with unescaped Unicode and slashes. Respond with 2xx after durable acceptance. Up to six attempts use a 15-second HTTP timeout. Transport failures, 408, 429 and 5xx are retryable; other HTTP refusals are terminal. Default delays between attempts are 10,20,40,80,160 seconds. Positive numeric Retry-After overrides the delay, capped at 300 seconds; HTTP-date values are not parsed. Ten consecutive terminal delivery failures disable the subscription. The timestamp/signature is regenerated each attempt; deduplicate using event ID and subscription ID. Fan-out counts a webhook as delivered when it is queued and can reset subscription failure counters before the HTTP attempt; the receiver audit is the authoritative record of receipt.",
                "security": [],
                "parameters": [
                    {
                        "name": "X-Momo-Signature",
                        "in": "header",
                        "required": false,
                        "description": "t=<unix seconds>,v1=<hex HMAC-SHA256 of timestamp + dot + raw body>. Use the subscription secret, constant-time comparison and a timestamp tolerance.",
                        "schema": {
                            "type": "string",
                            "example": "t=1918015200,v1=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
                        }
                    },
                    {
                        "name": "X-Momo-Event",
                        "in": "header",
                        "required": true,
                        "description": "Business event key.",
                        "schema": {
                            "type": "string",
                            "example": "record.created"
                        }
                    },
                    {
                        "name": "X-Momo-Event-Id",
                        "in": "header",
                        "required": true,
                        "description": "Stable event ID across retry attempts.",
                        "schema": {
                            "type": "string",
                            "example": "01953b60-4ce0-7000-8000-000000000001"
                        }
                    },
                    {
                        "name": "X-Momo-Subscription",
                        "in": "header",
                        "required": true,
                        "description": "Subscription receiving this event.",
                        "schema": {
                            "type": "string",
                            "example": "12"
                        }
                    },
                    {
                        "name": "X-Momo-Attempt",
                        "in": "header",
                        "required": true,
                        "description": "One-based queue attempt number.",
                        "schema": {
                            "type": "string",
                            "example": "1"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BusinessWebhookEvent"
                            },
                            "examples": {
                                "recordCreated": {
                                    "summary": "Business event envelope; publisher data varies",
                                    "value": {
                                        "id": "01953b60-4ce0-7000-8000-000000000001",
                                        "event": "record.created",
                                        "occurred_at": "2030-10-12T06:00:00+00:00",
                                        "tenant_id": 42,
                                        "subject": {
                                            "type": "data_record",
                                            "id": "01953b60-4ce0-7000-8000-000000000002"
                                        },
                                        "actor": {
                                            "kind": "api",
                                            "label": "ERP integration",
                                            "id": 7
                                        },
                                        "data": {
                                            "table": {
                                                "id": "01953b60-4ce0-7000-8000-000000000003",
                                                "name": "Customers",
                                                "slug": "customers"
                                            },
                                            "record_id": "01953b60-4ce0-7000-8000-000000000002",
                                            "record": {
                                                "name": "Example"
                                            },
                                            "source": "api"
                                        },
                                        "subscription": {
                                            "id": 12,
                                            "label": "Forward record changes"
                                        }
                                    }
                                },
                                "templateStatusChanged": {
                                    "summary": "template.status_changed \u2014 Meta approved a template",
                                    "value": {
                                        "event": "template.status_changed",
                                        "template_id": 418,
                                        "name": "order_shipped",
                                        "language": "sw",
                                        "category": "utility",
                                        "whatsapp_business_account_id": "102290129340398",
                                        "whatsapp_template_id": "1189456212345678",
                                        "previous_status": "in_review",
                                        "whatsapp_status": "approved",
                                        "rejection_reason": null,
                                        "timestamp": "2026-09-13T09:14:02+00:00"
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Receiver has durably accepted the event. Any 2xx response is acknowledged as successful."
                    }
                }
            }
        }
    }
}