{
    "openapi": "3.1.0",
    "info": {
        "title": "Momo Business Customer API",
        "version": "3.1.0",
        "description": "Customer integration reference for REST messaging, contacts, 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."
        },
        {
            "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."
        },
        {
            "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": "Contacts",
            "description": "Operate within a known contact group, using its numeric ID or UUID. Read/search and list are POST routes. Contact lookup accepts UID or numeric ID.\n\nPHONE or phone_number is required on both create and PATCH. Supply country_code explicitly when split normalization is needed. Updates recalculate the name and replace all custom fields; only omitted is_subscribed retains its previous value. The subscription flag is stored data and is not automatically applied by the current campaign dispatch loop."
        },
        {
            "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 use X-Signature and a flat event payload, with one delivery attempt. 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": "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 282 tools as 282 near-identical `POST` operations would validate perfectly and teach nobody anything. So what is documented under this tag is the **transport** \u2014 the 28 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| 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`, `data`, `approvals`, `payments`, `automations`, `alerts`, `operations`, `studio`, `numbers`, `agents`, `tickets`, `kb`, `content`, `calls`, `routing`, `meetings`, `comments`, `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 | ticked |\n| `mcp:numbers` | Phone numbers | ticked |\n| `mcp:meetings` | Meetings | ticked |\n| `mcp:builders` | Call flows and chat flows | ticked |\n| `mcp:data` | Data tables | ticked |\n| `mcp:studio` | Voice and audio | ticked |\n| `mcp:contacts` | Contacts | ticked |\n| `mcp:agents` | AI agents | ticked |\n| `mcp:commerce` | Orders and shop | ticked |\n| `mcp:support` | Support tickets | ticked |\n| `mcp:accounts` | Connected accounts | ticked |\n| `mcp:approvals` | Approvals | ticked |\n| `mcp:payments` | Payments | ticked |\n| `mcp:automations` | Automations | ticked |\n| `mcp:alerts` | Alerts and service levels | ticked |\n| `mcp:operations` | Operations | ticked |\n| `mcp:navigate` | Finding things | ticked |\n| `mcp:messaging` | Messaging | off |\n| `mcp:inbox` | Inbox | off |\n| `mcp:comments` | Comments | 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": "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, 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 and social \u2014 read, assign, reply.",
                    "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": "contacts",
                    "name": "Contacts",
                    "description": "The contact book and groups.",
                    "path": "/mcp/v1/contacts",
                    "module": "contacts"
                },
                {
                    "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"
                ],
                "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 and social.",
                            "mcp:comments": "Read comments on your Facebook, Instagram and TikTok posts.",
                            "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 or WhatsApp 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. 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"
                            }
                        }
                    }
                }
            },
            "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."
                    },
                    "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."
                    },
                    "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."
                    },
                    "retailer_id": {
                        "type": "string",
                        "description": "Your SKU. Unique per catalogue, and the id WhatsApp uses to refer to the product."
                    },
                    "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."
                    },
                    "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."
                    }
                }
            },
            "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."
                            }
                        }
                    },
                    "customer_wa_id": {
                        "type": "string",
                        "description": "The customer's WhatsApp id (their phone number in E.164 without +)."
                    },
                    "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."
                    },
                    "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; payload fields depend on this family.",
                        "enum": [
                            "message.received",
                            "message.sent",
                            "message.delivered",
                            "message.read",
                            "message.failed",
                            "message.echoed",
                            "message.updated",
                            "order.received",
                            "order.paid",
                            "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"
                        ]
                    },
                    "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."
                    },
                    "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": []
                    }
                },
                "required": [
                    "event",
                    "timestamp"
                ],
                "description": "Actual flat ChannelWebhook payload. Message events include message_id/direction/sender/recipient/status/body/media_url/channel_type. Orders and groups supply their own fields. 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"
                        ]
                    }
                }
            },
            "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. `readOnlyHint` marks a tool that only reads; `destructiveHint` marks one that changes the account.\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": "True when the tool only reads."
                            },
                            "destructiveHint": {
                                "type": "boolean",
                                "description": "True when the tool changes the account."
                            },
                            "idempotentHint": {
                                "type": "boolean",
                                "description": "True when calling twice with the same arguments is the same as calling once."
                            },
                            "openWorldHint": {
                                "type": "boolean",
                                "description": "True when the tool reaches something outside this platform."
                            },
                            "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",
                            "data",
                            "approvals",
                            "payments",
                            "automations",
                            "alerts",
                            "operations",
                            "studio",
                            "numbers",
                            "groups",
                            "agents",
                            "orders",
                            "shop",
                            "tickets",
                            "kb",
                            "content",
                            "calls",
                            "routing",
                            "meetings",
                            "messaging",
                            "inbox",
                            "comments",
                            "contacts",
                            "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.",
                                        "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.",
                                        "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."
                                    },
                                    "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).",
                        "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."
                                    },
                                    "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.",
                "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"
                    }
                }
            }
        },
        "/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.",
                "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"
                    }
                }
            }
        },
        "/api/v3/contacts/{group_id}/update/{uid}": {
            "patch": {
                "tags": [
                    "Contacts"
                ],
                "operationId": "v3ContactsUpdate",
                "summary": "Update a contact",
                "description": "Replacement-like contact update: phone remains required; send the name and all custom fields you intend to keep. Omitted is_subscribed retains its value; omitted custom fields are removed.",
                "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"
                    }
                }
            }
        },
        "/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.",
                "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"
                    }
                }
            }
        },
        "/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.",
                "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"
                    }
                }
            }
        },
        "/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"
                    }
                }
            }
        },
        "/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"
                    }
                }
            }
        },
        "/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": "Create one product. When the shop is connected to a Meta catalogue the product is created there first and the returned `meta_product_id` is stored; if Meta refuses, nothing is written locally and the call answers `502`.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "retailer_id",
                                    "name",
                                    "price",
                                    "currency",
                                    "image_url"
                                ],
                                "properties": {
                                    "retailer_id": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Your SKU. Must be unique inside this catalogue; WhatsApp refers to the product by it."
                                    },
                                    "name": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Product name as customers see it."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 5000,
                                        "description": "Long description."
                                    },
                                    "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 currency code."
                                    },
                                    "sale_price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Optional sale price in the minor unit."
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Publicly reachable image. Meta fetches it directly, so it cannot sit behind auth."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Link to the product on your own site."
                                    },
                                    "availability": {
                                        "type": "string",
                                        "enum": [
                                            "in stock",
                                            "out of stock",
                                            "preorder",
                                            "available for order",
                                            "discontinued"
                                        ],
                                        "description": "Stock state. Defaults to \"in stock\"."
                                    },
                                    "condition": {
                                        "type": "string",
                                        "enum": [
                                            "new",
                                            "refurbished",
                                            "used"
                                        ],
                                        "description": "Condition. Defaults to \"new\"."
                                    },
                                    "brand": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Brand name."
                                    },
                                    "category": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Category label."
                                    },
                                    "product_type": {
                                        "type": "string",
                                        "maxLength": 750,
                                        "description": "Your own taxonomy string."
                                    },
                                    "inventory": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Stock count."
                                    },
                                    "visibility": {
                                        "type": "string",
                                        "enum": [
                                            "staging",
                                            "published"
                                        ],
                                        "description": "Hide a product from customers with \"staging\"."
                                    }
                                }
                            },
                            "examples": {
                                "minimal": {
                                    "summary": "The five required fields",
                                    "value": {
                                        "retailer_id": "ACME-002",
                                        "name": "Kitenge 6 yards",
                                        "price": 45000,
                                        "currency": "TZS",
                                        "image_url": "https://cdn.acme.co.tz/kitenge.jpg"
                                    }
                                },
                                "full": {
                                    "summary": "A fully described product",
                                    "value": {
                                        "retailer_id": "ACME-003",
                                        "name": "Kanga Pair \u2014 Blue",
                                        "description": "Cotton kanga, 2 pieces, wax print.",
                                        "price": 25000,
                                        "sale_price": 19000,
                                        "currency": "TZS",
                                        "image_url": "https://cdn.acme.co.tz/kanga-blue.jpg",
                                        "url": "https://acme.co.tz/shop/kanga-blue",
                                        "availability": "in stock",
                                        "condition": "new",
                                        "brand": "Acme",
                                        "category": "Fabrics",
                                        "inventory": 40,
                                        "visibility": "published"
                                    }
                                },
                                "staged": {
                                    "summary": "Staged \u2014 created but hidden from customers",
                                    "value": {
                                        "retailer_id": "ACME-004",
                                        "name": "Ramadan Bundle",
                                        "price": 90000,
                                        "currency": "TZS",
                                        "image_url": "https://cdn.acme.co.tz/bundle.jpg",
                                        "visibility": "staging"
                                    }
                                }
                            }
                        }
                    }
                },
                "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": "Import products in bulk",
                "description": "Create or update up to 3000 products in one call, matched on `retailer_id` \u2014 an existing SKU is updated, a new one is created. When the shop is connected to Meta the mirror runs in the background and `data.syncing` says so.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "products"
                                ],
                                "properties": {
                                    "products": {
                                        "type": "array",
                                        "minItems": 1,
                                        "maxItems": 3000,
                                        "description": "The products to import.",
                                        "items": {
                                            "type": "object",
                                            "required": [
                                                "retailer_id",
                                                "name",
                                                "price",
                                                "currency",
                                                "image_url"
                                            ],
                                            "properties": {
                                                "retailer_id": {
                                                    "type": "string",
                                                    "maxLength": 100,
                                                    "description": "Your SKU. Must be unique inside this catalogue; WhatsApp refers to the product by it."
                                                },
                                                "name": {
                                                    "type": "string",
                                                    "maxLength": 100,
                                                    "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 currency code."
                                                },
                                                "image_url": {
                                                    "type": "string",
                                                    "format": "uri",
                                                    "maxLength": 2048,
                                                    "description": "Publicly reachable image. Meta fetches it directly, so it cannot sit behind auth."
                                                },
                                                "description": {
                                                    "type": "string",
                                                    "maxLength": 5000,
                                                    "description": "Long description."
                                                },
                                                "sale_price": {
                                                    "type": "integer",
                                                    "minimum": 0,
                                                    "description": "Optional sale price in the minor unit."
                                                },
                                                "availability": {
                                                    "type": "string",
                                                    "enum": [
                                                        "in stock",
                                                        "out of stock",
                                                        "preorder",
                                                        "available for order",
                                                        "discontinued"
                                                    ],
                                                    "description": "Stock state. Defaults to \"in stock\"."
                                                },
                                                "condition": {
                                                    "type": "string",
                                                    "enum": [
                                                        "new",
                                                        "refurbished",
                                                        "used"
                                                    ],
                                                    "description": "Condition. Defaults to \"new\"."
                                                },
                                                "brand": {
                                                    "type": "string",
                                                    "maxLength": 255,
                                                    "description": "Brand name."
                                                },
                                                "category": {
                                                    "type": "string",
                                                    "maxLength": 255,
                                                    "description": "Category label."
                                                },
                                                "inventory": {
                                                    "type": "integer",
                                                    "minimum": 0,
                                                    "description": "Stock count."
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            "example": {
                                "products": [
                                    {
                                        "retailer_id": "ACME-101",
                                        "name": "Vitenge Set",
                                        "price": 90000,
                                        "currency": "TZS",
                                        "image_url": "https://cdn.acme.co.tz/set.jpg"
                                    },
                                    {
                                        "retailer_id": "ACME-102",
                                        "name": "Khanga Pair",
                                        "price": 30000,
                                        "currency": "TZS",
                                        "image_url": "https://cdn.acme.co.tz/khanga.jpg",
                                        "inventory": 12
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "How many rows were written, and whether a Meta sync was started.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "type": "object",
                                    "required": [
                                        "status",
                                        "data"
                                    ],
                                    "properties": {
                                        "status": {
                                            "type": "string",
                                            "enum": [
                                                "success"
                                            ],
                                            "description": "Always \"success\"."
                                        },
                                        "data": {
                                            "type": "object",
                                            "required": [
                                                "imported",
                                                "syncing"
                                            ],
                                            "properties": {
                                                "imported": {
                                                    "type": "integer",
                                                    "description": "Rows created or updated."
                                                },
                                                "syncing": {
                                                    "type": "boolean",
                                                    "description": "True when a background sync to Meta was queued."
                                                }
                                            },
                                            "description": "What the import wrote."
                                        }
                                    }
                                },
                                "example": {
                                    "status": "success",
                                    "data": {
                                        "imported": 1,
                                        "syncing": 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/{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": "Partial update \u2014 send only what changes. `retailer_id` is immutable; create a new product instead. A product already mirrored to Meta is updated there first, and a Meta refusal answers `502` with nothing written locally.",
                "parameters": [
                    {
                        "$ref": "#/components/parameters/CatalogueId"
                    },
                    {
                        "$ref": "#/components/parameters/ProductId"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "description": "Any subset of the writable fields.",
                                "properties": {
                                    "name": {
                                        "type": "string",
                                        "maxLength": 100,
                                        "description": "Product name as customers see it."
                                    },
                                    "description": {
                                        "type": "string",
                                        "maxLength": 5000,
                                        "description": "Long description."
                                    },
                                    "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 currency code."
                                    },
                                    "sale_price": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Optional sale price in the minor unit."
                                    },
                                    "image_url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Publicly reachable image. Meta fetches it directly, so it cannot sit behind auth."
                                    },
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "maxLength": 2048,
                                        "description": "Link to the product on your own site."
                                    },
                                    "availability": {
                                        "type": "string",
                                        "enum": [
                                            "in stock",
                                            "out of stock",
                                            "preorder",
                                            "available for order",
                                            "discontinued"
                                        ],
                                        "description": "Stock state. Defaults to \"in stock\"."
                                    },
                                    "condition": {
                                        "type": "string",
                                        "enum": [
                                            "new",
                                            "refurbished",
                                            "used"
                                        ],
                                        "description": "Condition. Defaults to \"new\"."
                                    },
                                    "brand": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Brand name."
                                    },
                                    "category": {
                                        "type": "string",
                                        "maxLength": 255,
                                        "description": "Category label."
                                    },
                                    "inventory": {
                                        "type": "integer",
                                        "minimum": 0,
                                        "description": "Stock count."
                                    }
                                }
                            },
                            "examples": {
                                "price_change": {
                                    "summary": "Reprice",
                                    "value": {
                                        "price": 27000
                                    }
                                },
                                "out_of_stock": {
                                    "summary": "Mark out of stock",
                                    "value": {
                                        "availability": "out of stock",
                                        "inventory": 0
                                    }
                                },
                                "rename": {
                                    "summary": "Rename and re-photograph",
                                    "value": {
                                        "name": "Kanga Print Deluxe",
                                        "image_url": "https://cdn.acme.co.tz/kanga-deluxe.jpg"
                                    }
                                }
                            }
                        }
                    }
                },
                "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"
                    }
                ],
                "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 to a customer",
                "description": "Sends a single-product message: the product card with an *Add to cart* button. `catalogue_id` is the **Meta** catalogue id of a connected shop.",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "to",
                                    "catalogue_id",
                                    "product_retailer_id"
                                ],
                                "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."
                                    },
                                    "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."
                                    }
                                }
                            },
                            "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": "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-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."
                                    }
                                }
                            },
                            "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."
                                    }
                                }
                            },
                            "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"
                    }
                }
            }
        },
        "/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": true
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    "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| `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, 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 and social \u2014 read, assign, reply. |\n| `comments` | Comments | Comments on your Facebook, Instagram and TikTok posts. |\n| `contacts` | Contacts | The contact book and groups. |\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",
                                "data",
                                "approvals",
                                "payments",
                                "automations",
                                "alerts",
                                "operations",
                                "studio",
                                "numbers",
                                "groups",
                                "agents",
                                "orders",
                                "shop",
                                "tickets",
                                "kb",
                                "content",
                                "calls",
                                "routing",
                                "meetings",
                                "messaging",
                                "inbox",
                                "comments",
                                "contacts",
                                "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": true
                                                        }
                                                    }
                                                ]
                                            }
                                        }
                                    },
                                    "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: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: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": "Message and order events we POST to your server",
                "description": "Best-effort JSON POST to your configured public receiver. Verify X-Signature (plain hexadecimal HMAC-SHA256 of serialized body with endpoint secret). One attempt with 10-second timeout, no redirect following and no automatic retry/replay. Message payloads use local numeric message_id; order/group payloads have distinct fields. Secret retrieval/rotation is not currently exposed by customer UI/API.",
                "security": [],
                "parameters": [
                    {
                        "name": "X-Signature",
                        "in": "header",
                        "required": true,
                        "description": "Plain hex HMAC-SHA256 of the serialized JSON body using the endpoint signing secret; no sha256= prefix.",
                        "schema": {
                            "type": "string",
                            "pattern": "^[a-f0-9]{64}$"
                        },
                        "example": "0000000000000000000000000000000000000000000000000000000000000000"
                    }
                ],
                "requestBody": {
                    "required": true,
                    "description": "The event payload.",
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookEvent"
                            },
                            "examples": {
                                "message_delivered": {
                                    "summary": "A flat delivery callback",
                                    "value": {
                                        "event": "message.delivered",
                                        "message_id": 101,
                                        "direction": "outbound",
                                        "sender": "MyBrand",
                                        "recipient": "255712345678",
                                        "status": "delivered",
                                        "body": "Your order is ready.",
                                        "media_url": null,
                                        "channel_type": "sms",
                                        "timestamp": "2030-10-12T06:01:00+00:00"
                                    }
                                },
                                "order_received": {
                                    "summary": "A customer submitted a cart",
                                    "value": {
                                        "event": "order.received",
                                        "timestamp": "2030-10-12T06:01:00+00:00",
                                        "order_id": 201,
                                        "customer_wa_id": "255712345678",
                                        "customer_name": "Asha",
                                        "product_items": [
                                            {
                                                "product_retailer_id": "BAG-001",
                                                "quantity": 2,
                                                "item_price": 12500,
                                                "currency": "TZS"
                                            }
                                        ],
                                        "total_amount": 2500000,
                                        "total_currency": "TZS",
                                        "customer_note": null,
                                        "conversation_id": 31,
                                        "created_at": "2030-10-12T06:01:00+00:00"
                                    }
                                },
                                "order_paid": {
                                    "summary": "A payment settled",
                                    "value": {
                                        "event": "order.paid",
                                        "timestamp": "2030-10-12T06:05:00+00:00",
                                        "order_id": 201,
                                        "payment_id": 302,
                                        "method": "mobile_money",
                                        "amount_minor": 2500000,
                                        "currency": "TZS",
                                        "payer_msisdn": "255712345678",
                                        "paid_at": "2030-10-12T06:05:00+00:00",
                                        "conversation_id": 31
                                    }
                                }
                            }
                        }
                    }
                },
                "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"
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Receiver has durably accepted the event. Any 2xx response is acknowledged as successful."
                    }
                }
            }
        }
    }
}