{"openapi":"3.0.0","info":{"title":"Zigzapy WhatsApp API","version":"2.2.4"},"servers":[{"url":"https://zigzapy.app/api/v1"}],"tags":[{"name":"System","description":"System health monitoring, metrics, and application information"},{"name":"Webhook","description":"Webhook configuration and event subscription management"},{"name":"Session","description":"Session management, authentication, QR code generation, and connection handling"},{"name":"Session Network Route","description":"Fail-closed per-session mobile TCP egress through an isolated native tsnet node. Auth keys are write-only, single-use enrollment credentials and are never persisted or returned."},{"name":"Connector","description":"Embeddable Connector widget — mint short-lived ephemeral tokens and drive pairing (QR, phone code, passkey) from a browser without ever exposing the real instance token."},{"name":"Session S3","description":"Per-user S3 storage configuration for media delivery and retention"},{"name":"Session RabbitMQ","description":"Per-user RabbitMQ configuration for event publishing and queue management"},{"name":"Session Skips","description":"Per-user skip media download, groups, newsletters, broadcasts, own messages, and calls configuration"},{"name":"Session Global Transports","description":"Manage per-transport skip flags that control how the global dispatcher enriches events (webhook, RabbitMQ, SQS, Redis, WebSocket, and S3)"},{"name":"Session Echo","description":"Per-user echo settings for API messages"},{"name":"Session Presence","description":"Per-user presence management — controls automatic PresenceUnavailable after connect, mirroring WhatsApp Web's behavior so the contact sees \"last seen\" instead of \"online\" while idle"},{"name":"User","description":"User profile management, contacts, and account settings"},{"name":"User LID","description":"Link ID (LID) mapping and conversion between phone numbers and LIDs"},{"name":"Chat","description":"Chat operations including message retrieval, archiving, pinning, and muting"},{"name":"Send","description":"Send messages in all formats (text, media, documents, polls, buttons, lists, etc.).\n\n<b>API Echo Messages</b><br/>When the global flag <code>ECHO_API_MESSAGES_ENABLED</code> is true and the per-session echo setting is enabled, every successful API send emits a synthetic <code>Message</code> event through your configured transports/webhook. These events include the <code>Info.IsFromAPI: true</code> marker so downstream consumers can distinguish API-originated traffic. This ensures API-sent messages pass through the same filters/media pipeline as user-originated messages.\n\n<b>Per-Message Echo Control (EchoApi Field)</b><br/>All send endpoints support an optional <code>EchoApi</code> boolean field that provides <b>message-level control</b> over echo behavior. When set to <code>true</code>, the message will emit an API echo event <b>regardless</b> of global (<code>ECHO_API_MESSAGES_ENABLED</code>) or per-session (<code>echo_api_messages</code>) settings. This allows selective tracking of specific API-sent messages without enabling echo for all messages. The field is completely optional and defaults to respecting the configured echo settings when omitted. Use cases include: tracking critical business messages, monitoring specific conversation flows, or debugging individual message delivery."},{"name":"Label","description":"Chat labeling and organization features"},{"name":"Group","description":"Group management including creation, participant management, and group settings"},{"name":"Community","description":"Community and sub-group management, announcements, and join requests"},{"name":"Business","description":"WhatsApp Business features of the connected session: catalog and products, collections, cart, merchant compliance, business profile and cover photo, catalog/product/shop messages, orders, billing declarations, bots and sticker packs.\n\n**Typed catalog management routes** — `GET /business/linked-accounts`, `POST /business/eligibility`, `GET /business/catalog/{businessJID}/products/{productID}`, `POST /business/catalog/{businessJID}/products/query`, `GET /business/collections/{businessJID}/{collectionID}`, `POST /business/catalog`, `POST /business/products`, `PUT /business/products/{productID}`, `POST /business/products/delete`, `POST /business/products/image`, `PUT /business/products/{productID}/visibility`, `POST|PUT /business/collections…`, `POST /business/collections/delete|reorder`, `PUT /business/cart`, `POST …/appeal`, `GET|PUT /business/merchant-compliance`, `PUT /business/profile`, `POST /business/cover`, `DELETE /business/cover/{coverID}` — share one pipeline:\n- Request body (POST/PUT): exactly one JSON object, unknown fields rejected, at most 24 MiB → `400 invalid JSON body (maximum 24 MiB)`, `JSON object is required` or `exactly one JSON object is required`\n- Path IDs (`productID`, `collectionID`, `coverID`) must be non-blank and at most 256 bytes → `400 ID must contain 1-256 bytes`; `businessJID` must be `@s.whatsapp.net` or `@lid` → `400 businessJID must be a user JID`, and `limit`/`cursor` are validated on those routes\n- Validation runs before the session check, then `500 no session` / `client not connected`\n- Any WhatsApp failure, including validation inside the WhatsApp library, returns `502 business operation failed: <reason>`\n- The result is wrapped twice: `{\"code\":200,\"data\":{\"data\":…,\"success\":true},\"success\":true}`\n- Successful mutations clear this user's in-memory catalog cache (300 s)\n\n**Billing declarations** — `POST /business/order/charge/send`, `/business/order/accept`, `/business/order/status/send`, `/business/order/payment/status/send` and `/business/order/reject`:\n- Body: exactly one JSON object with unknown fields rejected (256 KiB for billing, 16 KiB for refusal) → `400`\n- `to` must be an individual buyer JID (`@s.whatsapp.net` or `@lid`, no device) and `id` at most 128 bytes\n- Then `500 no session` / `client not connected`, `409 own device identity unavailable`, `500 buyer identity lookup failed`\n- `502 … delivery is not confirmed` means WhatsApp did not acknowledge the send: do not retry blindly, the buyer may have received it\n- Only messages are sent: no bank or payment transaction is performed (`financial_transaction_performed: false`)\n\n**Prices** — catalog prices are integers in thousandths of the currency (`3000000` = 3,000.00; strings on typed routes), while billing amounts use `{value, offset}` (`value/offset`).\n"},{"name":"Device","description":"Device management, platform detection, and linked device information"},{"name":"Privacy","description":"Privacy settings, blocklist management, and disappearing message configuration"},{"name":"Newsletter","description":"Newsletter/channel management, subscriptions, and newsletter messaging"},{"name":"Status","description":"Status/story posting in various formats (text, image, video, audio)"},{"name":"Call","description":"Native VoIP calls engine (dial/answer/hangup/play/record + bidirectional s16le 16kHz PCM audio over /call/{call_id}/stream) plus legacy signaling control (reject/accept/preaccept/terminate/initiate)."},{"name":"Sync","description":"Synchronization and data consistency management"}],"paths":{"/session/echo/api":{"post":{"tags":["Session Echo"],"summary":"Turn API message echo events on or off","operationId":"configureEchoApiMessages","description":"Controls whether messages sent through this API also produce a synthetic `Message` event for this instance, so webhooks and transports see outgoing API messages like any other message.\n\n**Rules:**\n- With echo on, every successful send emits a `Message` event with `IsFromMe: true` and `Info.IsFromAPI: true`. It goes through the normal event pipeline (filters, media processing, webhook and transports).\n- Echo events are only emitted when the server-wide `ECHO_API_MESSAGES_ENABLED` environment variable is `true` **and** this flag is on.\n- A single send can force the echo regardless of both settings with `EchoApi`, `echoApi` or `echo_api` set to `true` in its request body.\n- Because echo events are own messages, `POST /session/skipownmessages/config` with `enabled: true` drops them.\n- `enabled` omitted (for example `{}`) is treated as `false` and disables echo.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EchoAPISettingsRequest"},"examples":{"enable":{"summary":"Emit events for API sends","description":"Webhook consumers receive the messages they sent through the API, flagged with `Info.IsFromAPI`.","value":{"enabled":true}},"disable":{"summary":"Stop emitting events for API sends","description":"Only messages received or sent from other devices generate events.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Flag stored and user configuration cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EchoAPISettingsUpdateResponse"},"example":{"code":200,"data":{"Details":"Echo API messages configuration updated successfully","EchoAPIMessages":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be stored or the user configuration cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update echo api messages configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to refresh configuration cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Echo"],"summary":"Get the API message echo setting","operationId":"getEchoApiMessagesConfig","description":"Returns whether this instance emits `Message` events for messages sent through the API.\n\n**Rules:**\n- `EchoAPIMessages` is the per-instance flag (`false` when never set).\n- Echo events are only emitted when the server-wide `ECHO_API_MESSAGES_ENABLED` is also `true`; that variable is not included in this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored echo flag.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EchoAPISettingsResponse"},"example":{"code":200,"data":{"EchoAPIMessages":true,"Details":"Echo API messages configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get echo api messages configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/list":{"get":{"tags":["Newsletter"],"summary":"List followed channels with raw WhatsApp metadata","description":"Returns every channel (newsletter) this account follows or owns, with the metadata exactly as WhatsApp returns it\n(`xwa2_newsletter_subscribed`). Use it when you need fields that `GET /newsletter/subscribed` flattens away,\nsuch as the channel state, verification badge, picture handles or reaction settings.\n\n**Features:**\n- One entry per channel in `data.Newsletter`, in the order returned by WhatsApp; the array is empty when the account follows no channel.\n- `thread_metadata` carries name, description, invite code, creation time, subscriber count and picture info.\n- `viewer_metadata` carries this account's `role` (`owner`, `admin`, `subscriber`, `guest`) and `mute` state; it may be `null`.\n\n**Rules:**\n- Numeric values such as `subscribers_count` and `creation_time` are JSON strings, as sent by WhatsApp.\n- Failures reported by WhatsApp use a legacy envelope: `success` stays `true` and the message is the string in `data`.\n- For a simplified list (`jid`, `name`, `subscribers`, `muted`...) use `GET /newsletter/subscribed`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Followed channels with the raw WhatsApp metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterRawListResponse"},"example":{"code":200,"data":{"Newsletter":[{"id":"120363000000000022@newsletter","state":{"type":"active"},"thread_metadata":{"creation_time":"1757900000","invite":"0029VaExampleInviteCode01","name":{"text":"Product Updates","id":"1757900000123456","update_time":"1757900000123456"},"description":{"text":"Release notes and product news","id":"1757900000654321","update_time":"1757900000654321"},"subscribers_count":"1500","verification":"unverified","picture":{"url":"https://mmg.whatsapp.net/v/t61.24694-24/example-channel-picture.jpg","id":"1757900001","type":"image","direct_path":"/v/t61.24694-24/example-channel-picture.jpg","hash":null},"preview":{"url":"https://mmg.whatsapp.net/v/t61.24694-24/example-channel-preview.jpg","id":"1757900001","type":"preview","direct_path":"/v/t61.24694-24/example-channel-preview.jpg","hash":null},"settings":{"reaction_codes":{"value":"all"}}},"viewer_metadata":{"mute":"off","role":"owner"}}]},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error. A WhatsApp query failure uses the legacy envelope (message string in `data`, `success: true`). The `no session` case uses the standard `ErrorEnvelope` (`error`, `success: false`), shown in the `no_session` example.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"list_failed":{"summary":"WhatsApp query failed (legacy envelope)","value":{"code":500,"data":"failed to get newsletter list: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/create":{"post":{"tags":["Newsletter"],"summary":"Create a channel","description":"Creates a WhatsApp channel (newsletter) owned by this account, optionally with a description and a picture.\nThe new channel JID is returned in `data.jid` and can be used right away with `POST /newsletter/send`.\nThe response does **not** include the invite code: call `POST /newsletter/info` with `{\"jid\": \"<data.jid>\"}` to read `invite_code`.\n\n**Rules:**\n- The body must be exactly one JSON object of at most 24 MiB; unknown keys are ignored.\n- `name` is required and cannot be blank. It is cut to its first 25 **bytes**, which may split a multi-byte character; `data.name` shows the value actually used.\n- `picture` accepts a base64 data URL or an HTTP(S) URL of a JPEG, PNG, GIF or WebP image. It is converted to a JPEG of at most 640x640 pixels before upload.\n- The account must have accepted the channel terms (`POST /newsletter/accept-tos`) **before** creating a channel; otherwise WhatsApp refuses the creation.\n\n**Error envelopes:**\n- Body and `name` validation errors and `no session` use the standard error envelope.\n- Picture errors (**400**) and a creation refused by WhatsApp (**500**) use a legacy envelope: `success` stays `true` and the failure is in `data.success: false` with `data.message`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterCreateRequest"},"examples":{"name_only":{"summary":"Name only","description":"Creates a channel without description or picture.","value":{"name":"Product Updates"}},"with_picture_url":{"summary":"Name, description and picture URL","description":"The picture is downloaded, converted to a JPEG of at most 640x640 and uploaded with the channel.","value":{"name":"Product Updates","description":"Release notes and product news","picture":"https://example.com/images/channel-cover.png"}},"with_picture_data_url":{"summary":"Picture as a base64 data URL","description":"Same as the URL variant, with the image embedded in the request (1x1 PNG shown).","value":{"name":"Product Updates","description":"Release notes and product news","picture":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg=="}}}}}},"responses":{"200":{"description":"Channel created; `data.jid` is the new channel JID. No invite code is returned — read it with `POST /newsletter/info`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterCreateResponse"},"example":{"code":200,"data":{"success":true,"jid":"120363000000000022@newsletter","name":"Product Updates","message":"Newsletter created successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid body or missing `name` (error envelope), or an unusable `picture` (legacy envelope with `success: true`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterLegacyErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not valid JSON or exceeds 24 MiB","value":{"code":400,"error":"invalid newsletter JSON (maximum 24 MiB)","success":false}},"several_objects":{"summary":"More than one JSON value in the body","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"name_required":{"summary":"name missing or blank","value":{"code":400,"error":"name is required","success":false}},"unsupported_picture_format":{"summary":"Picture is not JPEG, PNG, GIF or WebP (legacy envelope)","value":{"code":400,"data":{"success":false,"message":"Invalid image format. Supported: JPEG, PNG, GIF, WebP"},"success":true}},"invalid_picture_input":{"summary":"Picture is neither a data URL nor an HTTP(S) URL (legacy envelope)","value":{"code":400,"data":{"success":false,"message":"Error processing image: invalid media input: must be either base64 data URL or HTTP(S) URL"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user (error envelope), or WhatsApp refused the creation (legacy envelope with `success: true`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterLegacyErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"creation_refused":{"summary":"WhatsApp refused the creation (legacy envelope)","value":{"code":500,"data":{"success":false,"message":"Error creating newsletter: info query timed out"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/subscribed":{"get":{"tags":["Newsletter"],"summary":"List followed channels (simplified)","description":"Returns the channels this account follows or owns as a flat list with the most useful fields: JID, name,\ndescription, subscriber count, mute state and invite code.\n\n**Rules:**\n- `data.newsletters` is **omitted** (not an empty array) when the account follows no channel.\n- `muted` is `true` when this account muted the channel notifications.\n- `description` and `invite_code` are empty strings when WhatsApp does not return them.\n- A failure reported by WhatsApp uses a legacy envelope: `success` stays `true` and the failure is in `data.success: false` with `data.message`.\n- For the raw WhatsApp metadata (state, verification, pictures, role) use `GET /newsletter/list`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Followed channels in simplified form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSubscribedResponse"},"examples":{"with_channels":{"summary":"Account follows two channels","value":{"code":200,"data":{"success":true,"newsletters":[{"jid":"120363000000000022@newsletter","name":"Product Updates","description":"Release notes and product news","subscribers":1500,"muted":false,"invite_code":"0029VaExampleInviteCode01"},{"jid":"120363000000000033@newsletter","name":"Weekly Digest","description":"","subscribers":320,"muted":true,"invite_code":"0029VaExampleInviteCode02"}]},"success":true}},"no_channels":{"summary":"Account follows no channel","value":{"code":200,"data":{"success":true},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user (error envelope), or WhatsApp failed to return the list (legacy envelope with `success: true`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterLegacyErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"list_failed":{"summary":"WhatsApp query failed (legacy envelope)","value":{"code":500,"data":{"success":false,"message":"Error listing newsletters: websocket not connected"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/info":{"post":{"tags":["Newsletter"],"summary":"Get channel information by JID","description":"Fetches the metadata of one channel by its JID: name, description, subscriber count, invite code and, when\nWhatsApp returns viewer data, this account's mute state and role. The account does not need to follow the channel.\n\n**Rules:**\n- The channel JID is required and must be `<digits>@newsletter` without device. Send it as `NewsletterJID`, `newsletter_jid`, `jid`, `NewsletterID` or `newsletterID`, in the JSON body or in the query string.\n- When the JID is sent under several keys the values must be identical, otherwise the request fails with `conflicting newsletter parameters`.\n- The body must be a single JSON object of at most 1 MiB; keys other than the JID aliases are ignored.\n- `description`, `invite_code` and `role` are omitted when empty; `role` is `owner`, `admin`, `subscriber` or `guest`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NewsletterTargetRequest"},"examples":{"dashboard_field":{"summary":"Channel JID in the dashboard SDK field","description":"`NewsletterJID` is the field sent by the bundled dashboard SDK.","value":{"NewsletterJID":"120363000000000022@newsletter"}},"short_alias":{"summary":"Channel JID with the short alias","description":"`jid` and `newsletter_jid` are accepted as aliases of `NewsletterJID`.","value":{"jid":"120363000000000022@newsletter"}}}}}},"responses":{"200":{"description":"Channel metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterInfoResponse"},"example":{"code":200,"data":{"jid":"120363000000000022@newsletter","name":"Product Updates","description":"Release notes and product news","subscribers":1500,"invite_code":"0029VaExampleInviteCode01","muted":false,"role":"owner"},"success":true}}}},"400":{"description":"Bad Request: the body is not a single JSON object, or the channel JID is missing, invalid or conflicting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"JID missing or not a newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}},"conflicting_jid":{"summary":"Different JIDs under two aliases","value":{"code":400,"error":"conflicting newsletter parameters","success":false}},"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid newsletter JSON payload","success":false}},"non_string_jid":{"summary":"JID sent as a number","value":{"code":400,"error":"newsletter target must be a string","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: WhatsApp returned no channel for this JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"not_found":{"summary":"No channel returned","value":{"code":404,"error":"newsletter not found","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp failed to return the channel metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"info_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"error getting info: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/send":{"post":{"tags":["Newsletter"],"summary":"Publish a post to a channel","description":"Publishes a text, media or poll post to a channel this account owns or administers. Channel media is uploaded\nunencrypted and sent with the media handle, as the official client does.\n\n**Features:**\n- **Text:** `message`.\n- **Media:** `image`, `video`, `document`, `audio` or `sticker`, each as a base64 data URL or an HTTP(S) URL. `caption` applies to image, video and document.\n- **Poll:** `question` with at least 2 `options`; `max_answer` sets how many options a follower may pick.\n\n**Rules:**\n- `jid` is required and must be an `@newsletter` JID.\n- Send one content type. When several are present, the first non-empty one wins in this order: `message`, `image`, `video`, `document`, `audio`, `sticker`, poll.\n- Audio is always sent as a voice note (PTT) with a generated waveform; stickers are uploaded as images; `filename` (document name and title) defaults to `document`.\n- `max_answer` defaults to 1, values below 1 become 1, and a value above the number of options returns **400**. A `question` with fewer than 2 options counts as no content.\n- The whole request (download, upload and send) times out after 120 seconds.\n- `data.id` is the message ID. Reactions and view receipts need the numeric `server_id` from `POST /newsletter/messages`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSendRequest"},"examples":{"text":{"summary":"Text post","description":"Publishes a plain text post.","value":{"jid":"120363000000000022@newsletter","message":"Version 2.4 is live. Check the release notes on our website."}},"image_url":{"summary":"Image with caption (URL)","description":"The image is downloaded from the URL, uploaded to the channel media server and sent with a 72x72 thumbnail.","value":{"jid":"120363000000000022@newsletter","image":"https://example.com/images/release-2-4.jpg","caption":"Version 2.4 highlights"}},"document_url":{"summary":"Document with file name","description":"`filename` is used as the document name and title shown to followers.","value":{"jid":"120363000000000022@newsletter","document":"https://example.com/files/release-notes-2-4.pdf","filename":"release-notes-2-4.pdf","caption":"Full changelog"}},"voice_note":{"summary":"Voice note","description":"Audio is always delivered as a voice note (PTT).","value":{"jid":"120363000000000022@newsletter","audio":"https://example.com/audio/weekly-briefing.ogg"}},"poll":{"summary":"Single-choice poll","description":"A poll needs `question` and at least 2 `options`; `max_answer` 1 makes it single choice.","value":{"jid":"120363000000000022@newsletter","question":"Which feature should ship next?","options":["Dark mode","Offline sync","Shared folders"],"max_answer":1}}}}}},"responses":{"200":{"description":"Post published.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSendResponse"},"example":{"code":200,"data":{"success":true,"id":"3EB0C767D26A1D6B8A9F","timestamp":1757901234},"success":true}}}},"400":{"description":"Bad Request: invalid JSON or JID, no content, unusable media input, or `max_answer` above the number of options.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid JSON","success":false}},"invalid_jid":{"summary":"jid is missing or not an @newsletter JID","value":{"code":400,"error":"invalid JID","success":false}},"no_content":{"summary":"No text, media or valid poll in the body","value":{"code":400,"error":"no message content provided","success":false}},"invalid_media":{"summary":"Media is neither a data URL nor an HTTP(S) URL","value":{"code":400,"error":"error processing image: invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"max_answer_too_high":{"summary":"max_answer greater than the number of options","value":{"code":400,"error":"max_answer cannot be greater than options length (2)","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, media upload failure, or WhatsApp rejected the post.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Media upload failed","value":{"code":500,"error":"error uploading video: websocket not connected","success":false}},"send_failed":{"summary":"WhatsApp rejected the post","value":{"code":500,"error":"error sending message: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/follow":{"post":{"tags":["Newsletter"],"summary":"Follow a channel by JID","description":"Follows (subscribes to) a WhatsApp channel identified by its JID, so its posts appear in this account's Updates tab.\nUse `POST /newsletter/follow-invite` when you only have an invite code or link.\n\n**Rules:**\n- The channel JID is required (`<digits>@newsletter`, no device) under `NewsletterJID`, `newsletter_jid`, `jid`, `NewsletterID` or `newsletterID`, in the body or the query string; repeated values must match.\n- The body must be a single JSON object of at most 1 MiB. Other keys are ignored.\n- Following a channel that is already followed is passed to WhatsApp as is; the gateway does not check the current state.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NewsletterTargetRequest"},"examples":{"dashboard_field":{"summary":"Follow with the dashboard SDK field","description":"`NewsletterJID` is the field sent by the bundled dashboard SDK.","value":{"NewsletterJID":"120363000000000022@newsletter"}},"snake_case_alias":{"summary":"Follow with the snake_case alias","description":"`newsletter_jid` is equivalent to `NewsletterJID`; sending both with different values returns 400.","value":{"newsletter_jid":"120363000000000022@newsletter"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the follow request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"example":{"code":200,"data":{"success":true,"message":"Subscribed successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not a single JSON object, or the channel JID is missing, invalid or conflicting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"JID missing or not a newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}},"conflicting_jid":{"summary":"Different JIDs under two aliases","value":{"code":400,"error":"conflicting newsletter parameters","success":false}},"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid newsletter JSON payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the follow request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"follow_failed":{"summary":"WhatsApp rejected the request","value":{"code":500,"error":"error subscribing: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/follow-invite":{"post":{"tags":["Newsletter"],"summary":"Follow a channel by invite code or link","description":"Follows a WhatsApp channel from its invite code or `https://whatsapp.com/channel/...` link. The gateway first\nresolves the code to the channel metadata, then follows the resolved JID, which is returned in `data.jid`.\n\n**Rules:**\n- The invite is required under `Code`, `code`, `invite_code`, `NewsletterInviteCode` or `newsletterInviteCode`, in the body or the query string; repeated values must match.\n- Send either the bare code or the full channel link (the `https://whatsapp.com/channel/` prefix is stripped); maximum 2048 bytes.\n- The body must be a single JSON object of at most 1 MiB. Other keys are ignored.\n- An unknown or revoked code fails while resolving it (`error getting info: ...`), before any follow request is sent.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NewsletterTargetRequest"},"examples":{"invite_code":{"summary":"Follow with the bare invite code","description":"`Code` is the field sent by the bundled dashboard SDK.","value":{"Code":"0029VaExampleInviteCode01"}},"channel_link":{"summary":"Follow with the full channel link","description":"The link prefix is removed before the code is resolved; the lowercase `code` alias is accepted.","value":{"code":"https://whatsapp.com/channel/0029VaExampleInviteCode01"}}}}}},"responses":{"200":{"description":"Invite resolved and follow request accepted; `data.jid` is the followed channel.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterFollowInviteResponse"},"example":{"code":200,"data":{"success":true,"message":"Subscribed successfully","jid":"120363000000000022@newsletter"},"success":true}}}},"400":{"description":"Bad Request: the body is not a single JSON object, or the invite code is missing, too long or conflicting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_code":{"summary":"Invite code missing, blank or over 2048 bytes","value":{"code":400,"error":"newsletter invite code is required (maximum 2048 bytes)","success":false}},"conflicting_code":{"summary":"Different codes under two aliases","value":{"code":400,"error":"conflicting newsletter parameters","success":false}},"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid newsletter JSON payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: WhatsApp returned no channel for this invite code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"not_found":{"summary":"No channel returned","value":{"code":404,"error":"newsletter not found for invite","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the invite could not be resolved, or WhatsApp rejected the follow request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"resolve_failed":{"summary":"Invite code could not be resolved","value":{"code":500,"error":"error getting info: info query timed out","success":false}},"follow_failed":{"summary":"WhatsApp rejected the follow request","value":{"code":500,"error":"error subscribing: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/unfollow":{"post":{"tags":["Newsletter"],"summary":"Unfollow a channel by JID","description":"Unfollows (unsubscribes from) a WhatsApp channel identified by its JID, removing it from this account's followed channels.\nTo remove a channel you own for everyone, use `DELETE /newsletter/{newsletterID}` instead.\n\n**Rules:**\n- Send the channel JID (`<digits>@newsletter`, no device) as `NewsletterJID`, `newsletter_jid`, `jid`, `NewsletterID` or `newsletterID`, in the body or the query string. Values under several keys must be identical.\n- Only the JID is read; the body must be one JSON object (max 1 MiB).\n- Use `POST /newsletter/unfollow-invite` when you only have the invite link.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NewsletterTargetRequest"},"examples":{"dashboard_field":{"summary":"Unfollow with the dashboard SDK field","description":"`NewsletterJID` is the field sent by the bundled dashboard SDK.","value":{"NewsletterJID":"120363000000000022@newsletter"}},"short_alias":{"summary":"Unfollow with the short alias","description":"`jid` is accepted as an alias of `NewsletterJID`.","value":{"jid":"120363000000000022@newsletter"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the unfollow request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"example":{"code":200,"data":{"success":true,"message":"Unsubscribed successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not a single JSON object, or the channel JID is missing, invalid or conflicting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"JID missing or not a newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}},"conflicting_jid":{"summary":"Different JIDs under two aliases","value":{"code":400,"error":"conflicting newsletter parameters","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the unfollow request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"unfollow_failed":{"summary":"WhatsApp rejected the request","value":{"code":500,"error":"error unsubscribing: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/unfollow-invite":{"post":{"tags":["Newsletter"],"summary":"Unfollow a channel by invite code or link","description":"Unfollows a WhatsApp channel from its invite code or channel link. The gateway resolves the code to the channel\nJID first and then sends the unfollow request for that JID.\n\n**Rules:**\n- Send the invite as `Code`, `code`, `invite_code`, `NewsletterInviteCode` or `newsletterInviteCode` (body or query string); identical values are required when repeated.\n- The bare code and the `https://whatsapp.com/channel/<code>` link are both accepted, up to 2048 bytes.\n- Unlike `POST /newsletter/follow-invite`, the response does not include the resolved JID.\n- An unknown or revoked code fails while resolving it (`error getting info: ...`) and nothing is unfollowed.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NewsletterTargetRequest"},"examples":{"invite_code":{"summary":"Unfollow with the bare invite code","description":"`Code` is the field sent by the bundled dashboard SDK.","value":{"Code":"0029VaExampleInviteCode01"}},"channel_link":{"summary":"Unfollow with the full channel link","description":"`invite_code` is accepted as an alias; the link prefix is removed before resolving.","value":{"invite_code":"https://whatsapp.com/channel/0029VaExampleInviteCode01"}}}}}},"responses":{"200":{"description":"Invite resolved and unfollow request accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"example":{"code":200,"data":{"success":true,"message":"Unsubscribed successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not a single JSON object, or the invite code is missing, too long or conflicting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_code":{"summary":"Invite code missing, blank or over 2048 bytes","value":{"code":400,"error":"newsletter invite code is required (maximum 2048 bytes)","success":false}},"non_string_code":{"summary":"Invite code sent as a number","value":{"code":400,"error":"newsletter target must be a string","success":false}},"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid newsletter JSON payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: WhatsApp returned no channel for this invite code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"not_found":{"summary":"No channel returned","value":{"code":404,"error":"newsletter not found for invite","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the invite could not be resolved, or WhatsApp rejected the unfollow request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"resolve_failed":{"summary":"Invite code could not be resolved","value":{"code":500,"error":"error getting info: info query timed out","success":false}},"unfollow_failed":{"summary":"WhatsApp rejected the unfollow request","value":{"code":500,"error":"error unsubscribing: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/mute":{"post":{"tags":["Newsletter"],"summary":"Mute or unmute channel notifications","description":"Mutes or unmutes the notifications of a channel this account follows. Muting does not unfollow the channel; posts\nkeep arriving silently.\n\n**Rules:**\n- Channel JID required (`<digits>@newsletter`, no device) under `jid`, `NewsletterJID`, `newsletter_jid`, `NewsletterID` or `newsletterID`; the query string is accepted too.\n- `mute` (alias `Mute`) must be a JSON boolean: `true` mutes, `false` unmutes. Strings such as `\"true\"` are rejected. Omitted or `null` means `false` (unmute), as in the original contract.\n- When both `mute` and `Mute` are sent, `mute` wins.\n- The body must be a JSON object of at most 1 MiB; `null` values count as absent and data after the object is ignored.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterMuteRequest"},"examples":{"mute":{"summary":"Mute a channel","description":"Stops notifications for new posts of the channel.","value":{"jid":"120363000000000022@newsletter","mute":true}},"unmute":{"summary":"Unmute a channel","description":"Turns the channel notifications back on.","value":{"jid":"120363000000000022@newsletter","mute":false}}}}}},"responses":{"200":{"description":"WhatsApp applied the mute setting. `data.message` says `muted` or `enabled`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"examples":{"muted":{"summary":"Channel muted","value":{"code":200,"data":{"success":true,"message":"Notifications muted successfully"},"success":true}},"unmuted":{"summary":"Channel unmuted","value":{"code":200,"data":{"success":true,"message":"Notifications enabled successfully"},"success":true}}}}}},"400":{"description":"Bad Request: invalid body, invalid or conflicting channel JID, or `mute` not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"mute_not_boolean":{"summary":"mute is not a JSON boolean","value":{"code":400,"error":"mute must be a boolean","success":false}},"invalid_jid":{"summary":"JID missing or not a newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the mute change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"mute_failed":{"summary":"WhatsApp rejected the change","value":{"code":500,"error":"error changing mute: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/messages":{"post":{"tags":["Newsletter"],"summary":"List recent posts of a channel","description":"Returns recent posts of a channel with their view and reaction counts, text or caption and media details. Each\nitem's `server_id` is the ID required by `POST /newsletter/reaction` and `POST /newsletter/mark-viewed`.\n\n**Pagination:**\n- `limit` (aliases `count`, `Count`): 1-1000 posts, default 25.\n- `before_id` (aliases `before`, `Before`): only posts older than this server ID. Use the smallest `server_id` of the previous page.\n- Both accept a JSON number or a numeric string.\n\n**Rules:**\n- The channel JID is required under `NewsletterJID`, `newsletter_jid`, `jid`, `NewsletterID` or `newsletterID`, in the body or the query string; values repeated under several keys must be identical.\n- The body must be a single JSON object of at most 1 MiB.\n- `media` holds `type`, `mimetype`, `url`, `sha256` (base64) and `size`, plus `title` for documents and `duration` (seconds) for audio.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NewsletterTargetRequest"},"examples":{"latest_page":{"summary":"Latest 25 posts","description":"Without pagination fields the newest 25 posts are returned.","value":{"NewsletterJID":"120363000000000022@newsletter"}},"older_page":{"summary":"Next page with the dashboard fields","description":"Returns 10 posts older than server ID 120.","value":{"newsletter_jid":"120363000000000022@newsletter","limit":10,"before_id":"120"}},"legacy_aliases":{"summary":"Pagination with count and before aliases","description":"`count` and `before` are accepted as aliases of `limit` and `before_id`.","value":{"jid":"120363000000000022@newsletter","count":50,"before":120}}}}}},"responses":{"200":{"description":"Channel posts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterMessagesResponse"},"example":{"code":200,"data":{"success":true,"messages":[{"id":"3EB0C767D26A1D6B8A9F","server_id":121,"type":"text","timestamp":1757901234,"text":"Version 2.4 is live","views_count":42,"reaction_counts":{"👍":3}},{"id":"3EB0C767D26A1D6B8A9E","server_id":120,"type":"media","timestamp":1757897634,"caption":"Version 2.4 highlights","views_count":57,"media":{"type":"image","mimetype":"image/jpeg","url":"https://mmg.whatsapp.net/v/t62.7118-24/example-post-image.jpg","sha256":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg=","size":48213}}]},"success":true}}}},"400":{"description":"Bad Request: invalid body, missing or conflicting channel JID, or invalid pagination.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"JID missing or not a newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}},"count_out_of_range":{"summary":"limit outside 1-1000","value":{"code":400,"error":"newsletter count must be between 1 and 1000","success":false}},"invalid_before":{"summary":"before_id is negative or not numeric","value":{"code":400,"error":"before must be a nonnegative server message ID","success":false}},"wrong_type":{"summary":"limit sent as a boolean","value":{"code":400,"error":"newsletter parameter must be string or integer","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp failed to return the posts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"fetch_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"error getting messages: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/reaction":{"post":{"tags":["Newsletter"],"summary":"React to a channel post","description":"Sends a reaction from this account to a channel post, or removes the current reaction with an empty `reaction`.\n\n**Rules:**\n- `jid` (aliases `NewsletterJID`, `newsletter_jid`) must be an `@newsletter` JID.\n- `server_id` (alias `message_id`) is required: a positive numeric server ID as a number or string. Take it from `server_id` in `POST /newsletter/messages`; the `id` returned by `POST /newsletter/send` is not a server ID.\n- The session is checked first (**500** `no session`). As in the original contract, a missing or non-positive numeric `server_id` or a parseable JID that is not an `@newsletter` JID (for example `{}`) returns **500** `error sending reaction: ...`; nothing is sent to WhatsApp. A body that is not a JSON object, a field with the wrong type or a non-numeric string ID returns **400**.\n- `reaction` (alias `emoji`): the emoji to set; `\"\"`, `null` or omitted removes the reaction (original contract).\n- The body must be a JSON object of at most 1 MiB. Unknown keys are ignored, `null` values count as absent, key names are case-insensitive, and the canonical key wins over a differing alias.\n- Reacting is a follower action: when the channel owner reacts to its own post the call returns 200 but no reaction becomes visible.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterReactionRequest"},"examples":{"add_reaction":{"summary":"React with an emoji","description":"Adds or replaces this account's reaction on post 121.","value":{"jid":"120363000000000022@newsletter","server_id":121,"reaction":"👍"}},"remove_reaction":{"summary":"Remove the reaction","description":"An empty `reaction` removes this account's reaction.","value":{"jid":"120363000000000022@newsletter","server_id":121,"reaction":""}},"aliases":{"summary":"Dashboard aliases","description":"`NewsletterJID`, `message_id` (numeric string) and `emoji` are normalized to `jid`, `server_id` and `reaction`.","value":{"NewsletterJID":"120363000000000022@newsletter","message_id":"121","emoji":"❤️"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the reaction change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"example":{"code":200,"data":{"success":true,"message":"Reaction sent successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object, a field has the wrong type (including a non-numeric string `server_id`), or the JID cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid newsletter JSON object","success":false}},"invalid_type":{"summary":"A known field has the wrong JSON type","value":{"code":400,"error":"invalid newsletter parameter type","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, `server_id` missing or not positive, `jid` missing or not a newsletter JID (original contract), or WhatsApp rejected the reaction.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"invalid_server_id":{"summary":"server_id missing, zero or negative","value":{"code":500,"error":"error sending reaction: message ID must be a positive numeric server ID","success":false}},"invalid_jid":{"summary":"jid missing or not a newsletter JID","value":{"code":500,"error":"error sending reaction: invalid newsletter JID","success":false}},"reaction_failed":{"summary":"WhatsApp rejected the reaction","value":{"code":500,"error":"error sending reaction: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/mark-viewed":{"post":{"tags":["Newsletter"],"summary":"Mark channel posts as viewed","description":"Sends a view receipt for one or more channel posts. This is not the same as marking the chat as read on other\ndevices.\n\nA 200 only means the WhatsApp server acknowledged the view receipt. It does **not** guarantee that `views_count`\nincreases: the count seen by the channel owner may not reflect it (observed live on 2026-09-22).\n\n**Rules:**\n- `jid` (aliases `NewsletterJID`, `newsletter_jid`) must be an `@newsletter` JID.\n- `server_ids` (alias `message_ids`) is required: at least one positive server ID (numbers or numeric strings) from `POST /newsletter/messages`.\n- The session is checked first (**500** `no session`). As in the original contract, missing or empty `server_ids`, a non-positive numeric ID or a parseable JID that is not an `@newsletter` JID (for example `{}`) returns **500** `error marking as viewed: ...`; nothing is sent to WhatsApp. A body that is not a JSON object, a field with the wrong type or a non-numeric string ID returns **400**.\n- The body must be a JSON object of at most 1 MiB. Unknown keys are ignored and `null` values count as absent.\n- Repeating the call for the same posts also returns 200.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterMarkViewedRequest"},"examples":{"server_ids":{"summary":"Mark two posts as viewed","description":"Sends one view receipt covering posts 120 and 121.","value":{"jid":"120363000000000022@newsletter","server_ids":[120,121]}},"aliases":{"summary":"Dashboard aliases with string IDs","description":"`newsletter_jid` and `message_ids` are normalized; numeric strings are converted to numbers.","value":{"newsletter_jid":"120363000000000022@newsletter","message_ids":["120","121"]}}}}}},"responses":{"200":{"description":"The WhatsApp server acknowledged the view receipt (the owner's `views_count` may not change).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"example":{"code":200,"data":{"success":true,"message":"Messages marked as viewed"},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object, a field has the wrong type (including non-numeric string IDs), or the JID cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid newsletter JSON object","success":false}},"invalid_type":{"summary":"A known field has the wrong JSON type","value":{"code":400,"error":"invalid newsletter parameter type","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, `server_ids` missing, empty or not positive, `jid` missing or not a newsletter JID (original contract), or WhatsApp rejected the view receipt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"ids_required":{"summary":"server_ids missing or empty","value":{"code":500,"error":"error marking as viewed: provide at least one server message ID","success":false}},"invalid_id":{"summary":"An ID is zero or negative","value":{"code":500,"error":"error marking as viewed: message ID must be a positive numeric server ID","success":false}},"receipt_failed":{"summary":"WhatsApp rejected the receipt","value":{"code":500,"error":"error marking as viewed: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/subscribe-live-updates":{"post":{"tags":["Newsletter"],"summary":"Subscribe to live reaction and view updates of a channel","description":"Asks WhatsApp to push live reaction and view-count updates of a channel to this session for a limited time.\nWhatsApp answers with the subscription length in seconds (`data.duration`); renew the subscription before it expires.\n\n**Rules:**\n- Target channel: `NewsletterJID`, `newsletter_jid`, `jid`, `NewsletterID` or `newsletterID` (body or query string), formatted `<digits>@newsletter` without device; conflicting values under several keys return 400.\n- The body must be a single JSON object of at most 1 MiB; keys other than the channel aliases are ignored.\n- The WhatsApp request has its own 30-second timeout.\n- `duration` is `0` when WhatsApp does not state a length.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterLiveUpdatesRequest"},"examples":{"subscribe":{"summary":"Subscribe to live updates","description":"Starts (or renews) the live updates subscription of the channel.","value":{"jid":"120363000000000022@newsletter"}},"dashboard_field":{"summary":"Subscribe with the dashboard SDK field","description":"`NewsletterJID` is accepted as an alias of `jid`.","value":{"NewsletterJID":"120363000000000022@newsletter"}}}}}},"responses":{"200":{"description":"Subscription accepted; `data.duration` is its length in seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterLiveUpdatesResponse"},"example":{"code":200,"data":{"success":true,"duration":300,"message":"Subscribed to live updates"},"success":true}}}},"400":{"description":"Bad Request: the body is not a single JSON object, or the channel JID is missing, invalid or conflicting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"JID missing or not a newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}},"json_object_required":{"summary":"Body is JSON null","value":{"code":400,"error":"JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp did not accept the subscription within 30 seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"subscribe_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"error subscribing to live updates: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/message-updates":{"post":{"tags":["Newsletter"],"summary":"Get reaction and view-count updates of channel posts","description":"Returns the latest reaction and view counts of channel posts, like the official client's message-updates query.\nThe request always carries a cursor: `after`, `before`, or (when neither is sent) a cursor anchored on the newest post.\n\n**Cursor:**\n- `after`: updates for posts newer than this server ID.\n- `before`: updates for posts older than this server ID (exclusive). When `after` is also sent, `after` wins.\n- Neither: the gateway reads the newest post first and asks for the latest `count` posts; a channel without posts returns an empty list.\n- `count`: `0`, negative or omitted means 25; other values are passed to WhatsApp unchanged (original contract). `since` (Unix seconds) limits the result to changes after that time; negative cursors and `since` are ignored.\n\n**Rules:**\n- `jid` (aliases `NewsletterJID`, `newsletter_jid`) must be an `@newsletter` JID.\n- The body must be a JSON object of at most 1 MiB. Unknown keys (including the unsupported `message_ids`) are ignored and `null` values count as absent.\n- `media` in each update only carries `type`, `mimetype`, `url` (plus `title` for documents), and only for image, video and document posts.\n- WhatsApp may not answer this query; the call then fails with **500** `error getting updates: info query timed out`.\n- The session is checked first (**500** `no session`). As in the original contract, a missing `jid` or a parseable JID that is not an `@newsletter` JID (for example `{}`) returns **500** `error getting updates: invalid newsletter JID`; nothing is sent to WhatsApp. A body that is not a JSON object, a field with the wrong type or an unparseable JID returns **400**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterMessageUpdatesRequest"},"examples":{"latest":{"summary":"Updates of the latest 25 posts","description":"No cursor; the gateway anchors on the newest post.","value":{"jid":"120363000000000022@newsletter"}},"after_cursor":{"summary":"Updates for posts newer than a server ID","description":"Returns up to 50 updates for posts newer than server ID 120.","value":{"jid":"120363000000000022@newsletter","count":50,"after":120}},"before_since":{"summary":"Older posts changed since a time","description":"Posts older than server ID 121 whose counters changed after the given Unix time.","value":{"jid":"120363000000000022@newsletter","before":121,"since":1757890000}}}}}},"responses":{"200":{"description":"Updates of the selected posts; `data.updates` is empty when nothing matches.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterMessageUpdatesResponse"},"example":{"code":200,"data":{"success":true,"updates":[{"id":"3EB0C767D26A1D6B8A9F","server_id":121,"type":"text","timestamp":1757901234,"views_count":58,"reaction_counts":{"👍":5,"❤️":2},"text":"Version 2.4 is live"}]},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object, a field has the wrong type, or the JID cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_type":{"summary":"A known field has the wrong JSON type","value":{"code":400,"error":"invalid newsletter parameter type","success":false}},"invalid_json":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid newsletter JSON object","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, `jid` missing or not a newsletter JID (original contract), the newest post could not be read, or WhatsApp did not answer the updates query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"invalid_jid":{"summary":"jid missing or not a newsletter JID","value":{"code":500,"error":"error getting updates: invalid newsletter JID","success":false}},"query_timeout":{"summary":"WhatsApp did not answer","value":{"code":500,"error":"error getting updates: info query timed out","success":false}},"anchor_failed":{"summary":"Newest post could not be read","value":{"code":500,"error":"error getting updates: could not read the newest post to anchor the updates cursor: websocket not connected","success":false}}}}}},"501":{"description":"Not Implemented: the bundled WhatsApp library lacks the before-cursor updates query. The library shipped with this build implements it, so this is a defensive answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":501,"error":"error getting updates: the bundled WhatsApp library does not support this official newsletter operation yet","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/accept-tos":{"post":{"tags":["Newsletter"],"summary":"Accept a WhatsApp terms of service notice","description":"Accepts a WhatsApp terms of service notice for this account. Accepting the channel notice is required once before\n`POST /newsletter/create`; the defaults target that notice.\n\n**Rules:**\n- A JSON object is required: send `{}` to accept the channel notice with the defaults. An empty body returns **400** `invalid JSON`.\n- `notice_id` defaults to `20601218` and `stage` to `5` when omitted or empty. Both must be JSON strings; numbers are rejected as `invalid JSON`.\n- Unknown keys are ignored.\n- The session is checked before the body, so a missing session returns **500** even for an invalid body.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterAcceptTOSRequest"},"examples":{"channel_defaults":{"summary":"Accept the channel creation notice","description":"An empty object uses notice `20601218`, stage `5`.","value":{}},"explicit_notice":{"summary":"Explicit notice and stage","description":"Same notice as the defaults, sent explicitly.","value":{"notice_id":"20601218","stage":"5"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the notice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterActionResponse"},"example":{"code":200,"data":{"success":true,"message":"Terms of service accepted"},"success":true}}}},"400":{"description":"Bad Request: the body is empty, not valid JSON, or has non-string fields.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"invalid JSON","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the acceptance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"accept_failed":{"summary":"WhatsApp rejected the request","value":{"code":500,"error":"error accepting terms: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/admin-invite":{"post":{"tags":["Newsletter"],"summary":"Invite a contact to become a channel admin","description":"Invites a person to become admin of a channel this account owns, following the official client flow: the gateway\nfirst creates the invite on the WhatsApp server for the invitee's LID (the server returns the expiration) and only\nthen sends the `NewsletterAdminInviteMessage` carrying that expiration to the invitee.\n\n**Rules:**\n- `phone`, `newsletter_jid`, `image`, `caption` and `name` are all required and non-empty.\n- `phone` accepts a phone number, an `@s.whatsapp.net` JID or an `@lid` JID. Groups and other JID types are refused.\n- Phone numbers are resolved to a LID from the local store or a WhatsApp lookup; when no LID is found the call fails with **400** (message the contact first or pass the `@lid` JID).\n- `image` (base64 data URL or HTTP(S) URL) becomes a 96px JPEG thumbnail; an undecodable image is sent without thumbnail. It is fetched before `newsletter_jid` is validated.\n- `name` is the channel name shown in the invite card; the gateway does not read it from the channel.\n- A message sent without a server-side invite shows as \"invite cancelled\", which is why a refused invite (**502**) sends nothing.\n\n**Response:** `expires_at` is the server expiration (Unix seconds), `invitee_lid` the resolved LID and `invite_created` is always `true`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterAdminInviteRequest"},"examples":{"by_phone":{"summary":"Invite by phone number","description":"The number is resolved to the invitee's LID before the invite is created.","value":{"phone":"5511999999999","newsletter_jid":"120363000000000022@newsletter","image":"https://example.com/images/channel-cover.png","caption":"Join me as admin of Product Updates","name":"Product Updates"}},"by_lid":{"summary":"Invite by LID with a data URL image","description":"A `@lid` JID skips the LID lookup (1x1 PNG shown as image).","value":{"phone":"123456789012345@lid","newsletter_jid":"120363000000000022@newsletter","image":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","caption":"Join me as admin of Product Updates","name":"Product Updates"}}}}}},"responses":{"200":{"description":"Invite created on the server and invite message sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterAdminInviteResponse"},"example":{"code":200,"data":{"success":true,"id":"3EB0A1B2C3D4E5F60718","timestamp":1757901234,"recipient":"5511999999999","newsletter_jid":"120363000000000022@newsletter","invite_name":"Product Updates","expires_at":1758506034,"invitee_lid":"123456789012345@lid","invite_created":true,"message":"Newsletter admin invite sent successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, missing fields, unparseable phone, unusable image, invalid channel JID, non-person invitee or unresolvable LID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid JSON","success":false}},"missing_fields":{"summary":"A required field is empty","value":{"code":400,"error":"phone, newsletter_jid, image, caption and name are required","success":false}},"invalid_phone":{"summary":"phone cannot be parsed","value":{"code":400,"error":"could not parse phone number","success":false}},"invalid_newsletter_jid":{"summary":"newsletter_jid is not an @newsletter JID","value":{"code":400,"error":"invalid newsletter JID","success":false}},"not_a_person":{"summary":"phone is a group or another non-user JID","value":{"code":400,"error":"admin invites can only be sent to a person","success":false}},"lid_not_found":{"summary":"Invitee LID could not be resolved","value":{"code":400,"error":"could not resolve the invitee LID; send a message to this contact first or pass the @lid JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the invite message could not be sent after the server-side invite was created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Invite message not sent","value":{"code":500,"error":"error sending admin invite: websocket not connected","success":false}}}}}},"501":{"description":"Not Implemented: the bundled WhatsApp library cannot create admin invites. The library shipped with this build implements it, so this is a defensive answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":501,"error":"the bundled WhatsApp library does not support this official newsletter operation yet","success":false}}}},"502":{"description":"Bad Gateway: WhatsApp refused to create the invite (for example, this account is not the channel owner). No message is sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"whatsapp did not create the admin invite: info query timed out","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/health":{"get":{"tags":["System"],"summary":"Check server health","description":"Public liveness probe of the API. No authentication.\n\n**Rules:**\n- `200` with `status` `healthy` when the service answers normally, or `degraded` when it answers but slowly.\n- `503` with `status` `unhealthy` when the service or its database is down, or does not answer within 5 seconds.\n\n**Payload:** only `code`, `data`, `success` and `status`. No host, region, version or runtime details are returned.","security":[],"responses":{"200":{"description":"Service up (healthy or degraded).","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["code","data","success","status"],"properties":{"code":{"type":"integer","enum":[200,503],"description":"Same value as the HTTP status."},"data":{"type":"string","enum":["OK","ERROR"]},"success":{"type":"boolean"},"status":{"type":"string","enum":["healthy","degraded","unhealthy"]}}},"example":{"code":200,"data":"OK","success":true,"status":"healthy"}}}},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"description":"Service unavailable.\n\n**Pela API pública:** API sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["code","data","success","status"],"properties":{"code":{"type":"integer","enum":[200,503],"description":"Same value as the HTTP status."},"data":{"type":"string","enum":["OK","ERROR"]},"success":{"type":"boolean"},"status":{"type":"string","enum":["healthy","degraded","unhealthy"]}}},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":503,"data":"ERROR","success":false,"status":"unhealthy"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}}},"/webhook":{"get":{"tags":["Webhook"],"summary":"Get the instance webhook and subscribed events","description":"Returns the individual webhook URL of this instance and the event types it is subscribed to.\n\n**Rules:**\n- `webhook` is empty when no individual webhook is configured.\n- `subscribe` is the stored comma-separated list split into an array. When nothing is stored the array contains one empty string (`[\"\"]`).\n- The server-wide global webhook is configured by environment variables and is not part of this response.\n\n**Event types:**\n- **Messages:** `Message`, `UndecryptableMessage`, `FBMessage`, `Receipt`, `MediaRetry`, `ReadReceipt`\n- **Chat management:** `Star`, `Pin`, `Archive`, `Mute`, `MarkChatAsRead`, `ClearChat`, `DeleteChat`, `DeleteForMe`, `LabelAssociationChat`, `LabelAssociationMessage`, `LabelEdit`\n- **Groups and contacts:** `GroupInfo`, `JoinedGroup`, `Contact`, `Picture`, `PushName`, `BusinessName`, `UserAbout`\n- **Privacy:** `PrivacySettings`, `IdentityChange`, `Blocklist`, `BlocklistChange`, `UserStatusMute`\n- **Connection:** `Connected`, `Disconnected`, `QR`, `PairSuccess`, `PairError`, `QRScannedWithoutMultidevice`, `LoggedOut`, `StreamReplaced`, `StreamError`, `ConnectFailure`, `KeepAliveTimeout`, `KeepAliveRestored`, `ManualLoginReconnect`, `TemporaryBan`, `ClientOutdated`, `CATRefreshError`, `PasskeyRequest`, `PasskeyConfirmation`\n- **Calls:** `CallOffer`, `CallAccept`, `CallAcceptEngine`, `CallPreAccept`, `CallTransport`, `CallTerminate`, `CallTerminateEngine`, `CallRecordingReady`, `CallRecordingStopped`, `CallReject`, `CallOfferNotice`, `CallRelayLatency`, `CallReminder`, `UnknownCallEvent`\n- **Business:** `OrderState` (gateway-kept order state changed)\n- **Presence:** `Presence`, `ChatPresence`\n- **Newsletters:** `NewsletterJoin`, `NewsletterLeave`, `NewsletterMuteChange`, `NewsletterLiveUpdate`\n- **Sync:** `AppState`, `AppStateSyncComplete`, `AppStateSyncError`, `HistorySync`, `OfflineSyncPreview`, `OfflineSyncCompleted`, `PushNameSetting`, `UnarchiveChatsSetting`\n- **Special:** `All` subscribes to every event type\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored webhook URL and subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookGetResponse"},"examples":{"configured":{"summary":"Webhook with selected events","value":{"code":200,"data":{"webhook":"https://example.com/webhooks/whatsapp","subscribe":["Message","ReadReceipt","Connected"]},"success":true}},"not_configured":{"summary":"No webhook stored","value":{"code":200,"data":{"webhook":"","subscribe":[""]},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the webhook could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"could not get webhook: sql: database is closed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"post":{"tags":["Webhook"],"summary":"Set the instance webhook URL and events","description":"Sets the individual webhook URL of this instance and, optionally, replaces its event subscription.\n\n**Rules:**\n- `webhookurl` is stored as sent, without URL validation. An empty or omitted value clears the webhook and unregisters the individual webhook transport.\n- `events` omitted or empty: only the URL changes and the stored subscription is kept.\n- `events` non-empty: names are matched exactly (case-sensitive, no trimming), unknown names are silently discarded and the valid ones **replace** the stored subscription. If every name is unknown, the subscription becomes empty.\n- Event names are the ones listed in `GET /webhook`; `All` subscribes to every event type.\n\n**Side effects:**\n- The user cache is updated, live client subscriptions are refreshed and the individual webhook transport is registered in the event dispatcher.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSet"},"examples":{"with_events":{"summary":"URL and selected events","description":"Stores the URL and subscribes only to messages, read receipts and connection events.","value":{"webhookurl":"https://example.com/webhooks/whatsapp","events":["Message","ReadReceipt","Connected"]}},"all_events":{"summary":"URL and every event type","description":"`All` subscribes the webhook to every supported event type.","value":{"webhookurl":"https://example.com/webhooks/whatsapp","events":["All"]}},"url_only":{"summary":"Change only the URL","description":"Without `events`, the stored subscription is kept.","value":{"webhookurl":"https://example.com/webhooks/whatsapp-v2"}},"clear":{"summary":"Remove the webhook URL","description":"An empty URL unregisters the individual webhook transport; the stored subscription is kept.","value":{"webhookurl":""}}}}}},"responses":{"200":{"description":"Webhook stored. `data.webhook` echoes the stored URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookSetResponse"},"example":{"code":200,"data":{"webhook":"https://example.com/webhooks/whatsapp"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `events` is not an array of strings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the webhook could not be stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"could not set webhook: sql: database is closed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"put":{"tags":["Webhook"],"summary":"Update the webhook URL, events and activation","description":"Updates the individual webhook of this instance, with an explicit activation switch.\n\n**Rules:**\n- `active` defaults to `false` when omitted. With `active: false` the stored URL is cleared and the transport unregistered, whatever `webhookurl` says; send `active: true` to keep a webhook.\n- `events` non-empty: names are trimmed, unknown names silently discarded, and the valid list replaces the stored subscription. With `active: false` the subscription is cleared instead.\n- `events` omitted or empty: only the URL column is written and the stored subscription is kept.\n- `webhookurl` is stored without URL validation.\n\n**Response:**\n- `data.webhook` is the stored URL (empty when inactive), `data.events` the accepted event names (`null` when none was sent or accepted) and `data.active` echoes the request.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookUpdate"},"examples":{"activate":{"summary":"Activate with URL and events","description":"Stores the URL, replaces the subscription and registers the webhook transport.","value":{"webhookurl":"https://example.com/webhooks/whatsapp","events":["Message","ReadReceipt"],"active":true}},"url_only":{"summary":"Change the URL and keep the events","description":"Without `events`, only the URL changes. `active` must be `true` or the URL is cleared.","value":{"webhookurl":"https://example.com/webhooks/whatsapp-v2","active":true}},"deactivate":{"summary":"Deactivate and clear the subscription","description":"`active: false` with a non-empty `events` clears both the URL and the stored subscription.","value":{"webhookurl":"","events":["Message"],"active":false}}}}}},"responses":{"200":{"description":"Webhook updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookUpdateResponse"},"examples":{"active":{"summary":"Active webhook","value":{"code":200,"data":{"active":true,"events":["Message","ReadReceipt"],"webhook":"https://example.com/webhooks/whatsapp"},"success":true}},"inactive":{"summary":"Deactivated webhook","value":{"code":200,"data":{"active":false,"events":["Message"],"webhook":""},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON or a field has the wrong type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the webhook could not be stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"could not update webhook: sql: database is closed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"delete":{"tags":["Webhook"],"summary":"Delete the instance webhook and its events","description":"Removes the individual webhook of this instance: the URL and the event subscription are both cleared.\n\n**Rules:**\n- No request body.\n- The individual webhook transport is unregistered from the event dispatcher and the user cache is updated.\n- The server-wide global webhook and other transports (RabbitMQ, SQS, Redis, WebSocket) are not affected.\n- Deleting when no webhook is configured still returns **200**.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Webhook URL and events cleared.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeleteResponse"},"example":{"code":200,"data":{"Details":"Webhook and events deleted successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the webhook could not be removed from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"could not delete webhook: sql: database is closed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/connect":{"post":{"tags":["Session"],"summary":"Connect the instance to WhatsApp","description":"Starts the WhatsApp client of this instance in the background and stores the event subscription used by its individual webhook.\n\nWithout a stored session the client starts in pairing mode: read the code with `GET /session/qr` or request a phone code with `POST /session/pairphone`. A stored, valid session reconnects without scanning. Use this endpoint again after `POST /session/disconnect`.\n\n**Rules:**\n- The body is required; an empty body returns `400 could not decode Payload`. Send at least `{}`. Field names are matched case-insensitively.\n- `Subscribe` **replaces** the stored subscription (`users.events`) on every call. Unknown names are discarded and duplicates removed; omitting it, sending `[]` or only unknown names stores an empty subscription, which stops individual webhook deliveries (global transports are not affected). Send `[\"All\"]` to receive every event.\n- `Immediate: false` (default) blocks for about 10 seconds and returns `500 failed to connect` when the socket is not up by then. `Immediate: true` returns at once; check `GET /session/status` afterwards.\n- A connected client returns `500 already connected`; a stale, disconnected client is cleaned up and replaced.\n- `data.jid` and `data.webhook` are the values stored before this call (`jid` is empty before the first pairing); `data.events` is the new comma-separated subscription.\n\n**Event names:** `Message`, `ReadReceipt`, `Receipt`, `Presence`, `ChatPresence`, `GroupInfo`, `Connected`, `Disconnected`, `LoggedOut`, `QR`, `PairSuccess`, `CallOffer`, `CallTerminate`, `NewsletterJoin`, `HistorySync`, `All` and the rest of `supportedEventTypes` in `constants.go`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Connect"},"examples":{"selected_events":{"summary":"Subscribe to selected events and return immediately","description":"Stores `Message,ReadReceipt,Connected` as the individual webhook subscription and answers without waiting for the socket.","value":{"Subscribe":["Message","ReadReceipt","Connected"],"Immediate":true}},"all_events_wait":{"summary":"All events, wait up to 10 seconds","description":"Blocks for about 10 seconds and fails with 500 when the client is not connected by then.","value":{"Subscribe":["All"],"Immediate":false}},"no_subscription":{"summary":"Connect without individual webhook events","description":"Omitting `Subscribe` clears the stored subscription; global transports still receive events.","value":{"Immediate":true}}}}}},"responses":{"200":{"description":"Client started. With `Immediate:false` the socket was connected within the wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionConnectResponse"},"examples":{"paired_session":{"summary":"Stored session reconnected","value":{"code":200,"data":{"details":"Connected!","events":"Message,ReadReceipt,Connected","jid":"5511999999999:12@s.whatsapp.net","skip_media_download":false,"webhook":"https://example.com/webhook"},"success":true}},"first_pairing":{"summary":"New instance, waiting for QR scan","value":{"code":200,"data":{"details":"Connected!","events":"All","jid":"","skip_media_download":false,"webhook":""},"success":true}}}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the client is already connected, or the socket did not connect within the 10-second wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"already_connected":{"summary":"A connected client already exists","value":{"code":500,"error":"already connected","success":false}},"failed_to_connect":{"summary":"Socket not connected after the wait","value":{"code":500,"error":"failed to connect","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/disconnect":{"post":{"tags":["Session"],"summary":"Disconnect from WhatsApp and keep the session","description":"Closes the WhatsApp socket of this instance while keeping the paired device credentials, so `POST /session/connect` can resume later without scanning a QR code again.\n\n**Rules:**\n- No request body is read.\n- Requires a client in memory; otherwise returns `500 no session`.\n- When the client was connected or logged in, a synthetic `Disconnected` event (`source: session/disconnect`, `synthetic: true`) is dispatched to the configured webhooks before cleanup.\n- The client resources are released, the `connected` flag is cleared in the database and any stored QR code is discarded.\n- `wasConnected` / `wasLoggedIn` report the client state immediately before the call.\n\n**Use Cases:**\n- Pause event delivery during maintenance\n- Apply a new proxy (`POST /session/proxy` requires a disconnected client)\n- Use `POST /session/logout` instead to unlink the device for good\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Client disconnected; the paired session is kept.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDisconnectResponse"},"example":{"code":200,"data":{"Details":"Disconnected successfully","wasConnected":true,"wasLoggedIn":true},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for this instance (never connected, or already disconnected).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/logout":{"post":{"tags":["Session"],"summary":"Log out and unlink the device","description":"Logs the linked device out of WhatsApp and removes the local session, so the next `POST /session/connect` starts a fresh pairing (QR code or phone code).\n\n**Rules:**\n- No request body is read.\n- Requires a client in memory; otherwise returns `500 no session`.\n- When the client is logged in, the gateway asks WhatsApp to remove the device (30-second timeout). The local cleanup always runs, even when that request fails; `logoutSuccess: false` tells that WhatsApp did not confirm the removal.\n- A client that was not logged in is only cleaned up and reports `logoutSuccess: true`.\n- The stored QR code is cleared and the `connected` flag is reset.\n\n**Use Cases:**\n- Revoke API access to a WhatsApp account\n- Switch the instance to another phone number\n- Use `POST /session/disconnect` to pause without unlinking\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Local session removed. Check `logoutSuccess` to know whether WhatsApp confirmed the device removal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionLogoutResponse"},"examples":{"logged_out":{"summary":"Device removed from WhatsApp","value":{"code":200,"data":{"Details":"Logout completed","logoutSuccess":true,"wasConnected":true,"wasLoggedIn":true},"success":true}},"cleanup_only":{"summary":"WhatsApp did not confirm; local session removed anyway","value":{"code":200,"data":{"Details":"Logout completed","logoutSuccess":false,"wasConnected":false,"wasLoggedIn":true},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/refresh":{"post":{"tags":["Session"],"summary":"Reconnect and resynchronize the session","description":"Restarts the WhatsApp client of an already paired instance and, once the socket is back, optionally resynchronizes app state, pre-keys and privacy settings.\n\n**Features:**\n- **Reconnect:** releases the current client, starts a new one with the stored subscription and waits 3 seconds.\n- **App state:** fetches the five collections `critical_block`, `critical_unblock_low`, `regular_low`, `regular_high` and `regular` from scratch.\n- **Auto recovery:** when a collection fails, asks the primary phone for an app-state recovery snapshot.\n- **Pre-keys:** reads the server pre-key count and uploads new keys when fewer than 5 remain.\n- **Privacy:** fetches the privacy settings bypassing the cache.\n\n**Rules:**\n- The body is optional; every flag defaults to `true`. An unreadable body is ignored and the defaults are used.\n- The instance must have a stored JID; before the first pairing the call returns `400`.\n- The sync steps only run when the new client is connected after the 3-second wait. `sync` and `sync_options` are omitted otherwise, or when all flags are `false`.\n- When the new client is not connected, the response is **500** but keeps the legacy envelope: `success: true` at the top level and the details in `data` with `refreshSuccess: false`.\n- Typical duration: 4 to 10 seconds. Do not call it in a tight loop.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRefreshRequest"},"examples":{"full_refresh":{"summary":"Full refresh (same as an empty body)","description":"Reconnects and runs every sync step with automatic recovery.","value":{"sync_app_state":true,"refresh_prekeys":true,"refresh_privacy":true,"auto_recovery":true}},"reconnect_only":{"summary":"Reconnect without sync steps","description":"Only restarts the client; `sync` and `sync_options` are omitted from the response.","value":{"sync_app_state":false,"refresh_prekeys":false,"refresh_privacy":false}},"app_state_without_recovery":{"summary":"Resync app state without asking the phone for recovery","description":"Runs the app-state fetch only and never sends recovery requests to the primary device.","value":{"sync_app_state":true,"refresh_prekeys":false,"refresh_privacy":false,"auto_recovery":false}}}}}},"responses":{"200":{"description":"Client reconnected; `data.sync` holds the result of each requested step.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRefreshResponse"},"example":{"code":200,"data":{"Details":"Connection refresh completed","refreshSuccess":true,"wasConnected":true,"wasLoggedIn":true,"newConnected":true,"newLoggedIn":true,"jid":"5511999999999:12@s.whatsapp.net","sync_options":{"sync_app_state":true,"refresh_prekeys":true,"refresh_privacy":true,"auto_recovery":true},"sync":{"app_state":[{"name":"critical_block","success":true,"duration":"1.234s"},{"name":"critical_unblock_low","success":true,"duration":"856.1ms"},{"name":"regular_low","success":true,"duration":"523.4ms"},{"name":"regular_high","success":false,"error":"failed to verify patch v42: mismatching LTHash","duration":"412.9ms","recovery_requested":true},{"name":"regular","success":true,"duration":"678.2ms"}],"prekeys":{"checked":true,"server_count":47},"privacy_settings":{"fetched":true},"total_duration":"4.521s"}},"success":true}}}},"400":{"description":"Bad Request: the instance has never been paired, so there is no JID to reconnect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"no JID found, QR scan required for initial pairing","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error. When the new client is not connected after the wait, the body keeps the legacy envelope (`success: true`, details in `data`, `data.error` set). A response that cannot be encoded uses the error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRefreshFailureResponse"},"examples":{"not_reconnected":{"summary":"Client did not reconnect (legacy envelope)","value":{"code":500,"data":{"Details":"Connection refresh completed","error":"Failed to refresh connection","refreshSuccess":false,"wasConnected":true,"wasLoggedIn":true,"newConnected":false,"newLoggedIn":false,"jid":"5511999999999:12@s.whatsapp.net"},"success":true}},"encoding_failed":{"summary":"Response could not be encoded","value":{"code":500,"error":"json: unsupported value: NaN","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/status":{"get":{"tags":["Session"],"summary":"Get connection, pairing and configuration status","description":"Returns a snapshot of the instance: socket and login state, connection health, stored configuration (webhook, events, skip flags, proxy, S3, RabbitMQ) and the pending passkey pairing state.\n\n**Rules:**\n- Always answers 200 for a valid token, even without a client (`hasClient: false`, `connectionHealth: no_client`).\n- `connectionHealth` is derived in this order: `no_client`, `disconnected`, `connected_not_logged`, `connected`.\n- `expiration` is the remaining lifetime in seconds computed from the stored expiration timestamp; without a stored expiration it is the negative current Unix time.\n- `avatar_url` comes from a 24-hour cache; when it is empty and the session is logged in, the avatar is fetched in the background for the next call.\n- The configuration blocks are read from the database. When that read fails, `s3_config` and `rabbitmq_config` fall back to `{\"enabled\": false}`.\n- The response includes secrets stored for the instance (the instance `token`, the S3 access key and the RabbitMQ URL). Call it only from trusted backends; the browser-facing `GET /connector/status` removes them.\n- `isFromAPI` mirrors `echo_api_messages`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Status snapshot of the instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStatusResponse"},"examples":{"connected":{"summary":"Paired and connected instance","value":{"code":200,"data":{"id":"bec45bb93cbd24cbec32941ec3c93a12","name":"Support Line","avatar_url":"https://pps.whatsapp.net/v/t61.24694-24/example_avatar.jpg","connected":true,"loggedIn":true,"hasClient":true,"connectionHealth":"connected","lastSuccessfulConnect":1757862000,"autoReconnectErrors":0,"enableAutoReconnect":true,"expiration":86400,"token":"a1b2c3d4e5f6a7b8c9d0","jid":"5511999999999:12@s.whatsapp.net","webhook":"https://example.com/webhook","events":"Message,ReadReceipt","proxy_url":"","qrcode":"","skip_media_download":false,"skip_groups":false,"skip_newsletters":false,"skip_broadcasts":true,"skip_own_messages":false,"echo_api_messages":false,"skip_calls":false,"call_reject_message":"Sorry, I cannot take calls at the moment.","call_reject_type":"busy","globalTransportSkips":{"skipGlobalWebhook":false,"skipGlobalRabbitMQ":false,"skipGlobalSQS":false,"skipGlobalRedis":false,"skipGlobalWebSocket":false,"skipGlobalS3":false},"isFromAPI":false,"auto_presence_unavailable":false,"proxy_config":{"enabled":false,"proxy_url":""},"s3_config":{"enabled":true,"endpoint":"https://s3.us-east-1.amazonaws.com","region":"us-east-1","bucket":"example-whatsapp-media","access_key":"AKIAIOSFODNN7EXAMPLE","path_style":false,"public_url":"https://cdn.example.com","media_delivery":"both","retention_days":30,"disable_acl":true},"rabbitmq_config":{"enabled":false,"url":"","exchange":"","exchange_type":"","queue":"","queue_type":"","routing_key":"","events":"","durable":false,"auto_delete":false,"exclusive":false,"no_wait":false,"delivery_mode":0,"dead_letter_exchange":"","dead_letter_routing_key":"","message_ttl":0,"max_length":0,"max_length_bytes":0,"queue_arguments":"","exchange_arguments":""},"passkeyRequired":false,"passkeyResponseSubmitted":false,"passkeyConfirmed":false,"passkeyConfirmationCode":"","passkeySkipHandoffUX":false,"passkeyError":"","timestamp":1757865600},"success":true}},"no_client":{"summary":"Instance created but never connected","value":{"code":200,"data":{"id":"5663e0c52063ec35d0ba45f7c2011c06","name":"New Instance","avatar_url":"","connected":false,"loggedIn":false,"hasClient":false,"connectionHealth":"no_client","lastSuccessfulConnect":0,"autoReconnectErrors":0,"enableAutoReconnect":false,"expiration":-1757865600,"token":"f0e1d2c3b4a5968778695a4b","jid":"","webhook":"","events":"","proxy_url":"","qrcode":"","skip_media_download":false,"skip_groups":false,"skip_newsletters":false,"skip_broadcasts":false,"skip_own_messages":false,"echo_api_messages":false,"skip_calls":false,"call_reject_message":"","call_reject_type":"","globalTransportSkips":{"skipGlobalWebhook":false,"skipGlobalRabbitMQ":false,"skipGlobalSQS":false,"skipGlobalRedis":false,"skipGlobalWebSocket":false,"skipGlobalS3":false},"isFromAPI":false,"auto_presence_unavailable":false,"proxy_config":{"enabled":false,"proxy_url":""},"s3_config":{"enabled":false},"rabbitmq_config":{"enabled":false},"passkeyRequired":false,"passkeyResponseSubmitted":false,"passkeyConfirmed":false,"passkeyConfirmationCode":"","passkeySkipHandoffUX":false,"passkeyError":"","timestamp":1757865600},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the token lookup in the database failed, or the status could not be encoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"sql: database is closed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/pairphone":{"post":{"tags":["Session"],"summary":"Get a phone pairing code","description":"Requests an 8-character linking code for pairing by phone number instead of scanning a QR code. The user types the code on the phone under **Linked devices > Link with phone number**.\n\n**Rules:**\n- The instance must be connected first (`POST /session/connect`) and not paired yet; a paired instance returns `400 already paired`, a missing client `500 no session`.\n- `Phone` is required: the full number with country code, digits only.\n- `client_type` (optional, case-insensitive) chooses the device label shown on the phone; omitted or empty keeps `chrome` (\"Chrome (Linux)\"). Any other value returns `400`.\n- A rejection from WhatsApp (for example an invalid number or too many attempts) is returned as `400` with the upstream error text.\n\n**Use Cases:**\n- Pair headless servers without a camera\n- Show a \"macOS\" or \"Android\" label instead of the default browser label\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pairphone"},"examples":{"default_chrome":{"summary":"Default device label","description":"Without `client_type` the phone shows \"Chrome (Linux)\".","value":{"Phone":"5511999999999"}},"macos_label":{"summary":"Show the code as a macOS device","description":"The phone lists the new linked device as \"macOS\".","value":{"Phone":"5511999999999","client_type":"macos"}},"android_label":{"summary":"Show the code as an Android device","description":"`client_type` is case-insensitive, so `Android` is accepted.","value":{"Phone":"5511999999999","client_type":"Android"}}}}}},"responses":{"200":{"description":"Linking code generated. It must be typed on the phone before it expires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPairPhoneResponse"},"example":{"code":200,"data":{"LinkingCode":"9H3J-H3J8"},"success":true}}}},"400":{"description":"Bad Request: invalid body, missing `Phone`, unsupported `client_type`, instance already paired, or WhatsApp rejected the pairing request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone":{"summary":"Phone missing","value":{"code":400,"error":"missing Phone in Payload","success":false}},"invalid_client_type":{"summary":"Unsupported client_type","value":{"code":400,"error":"invalid client_type: accepted values are unknown, chrome, edge, firefox, ie, opera, safari, electron, uwp, otherwebclient, macos, android","success":false}},"already_paired":{"summary":"Instance is already paired","value":{"code":400,"error":"already paired","success":false}},"upstream_rejected":{"summary":"WhatsApp rejected the request","value":{"code":400,"error":"server returned error 429: rate-overlimit","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory; call `POST /session/connect` first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/passkey/status":{"get":{"tags":["Session"],"summary":"Get the passkey pairing state","description":"Returns the in-memory passkey pairing state of the instance: the WebAuthn challenge to sign, whether a response was submitted, and the confirmation code once WhatsApp sends it.\n\n**Flow:**\n- `POST /session/connect`, then poll this endpoint (or call `POST /session/passkey/challenge` to obtain the challenge on demand).\n- Pass `challenge` verbatim to `navigator.credentials.get({publicKey})` at the origin `https://web.whatsapp.com`, then send the assertion to `POST /session/passkey/response`.\n- When `confirmationCode` appears and `skipHandoffUX` is false, the user compares the code on the phone and you call `POST /session/passkey/confirm`. With `skipHandoffUX: true` the gateway confirms automatically.\n\n**Rules:**\n- Always 200 for a valid token; without any passkey activity every field has its idle value and `challenge` is `null`.\n- `required` is `true` while a challenge is stored and not confirmed.\n- Binary WebAuthn fields (`challenge.challenge`, `allowCredentials[].id`) are base64url without padding.\n- A successful confirm clears the state, so the next call returns the idle snapshot.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Passkey state snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeyStatusResponse"},"examples":{"idle":{"summary":"No passkey challenge pending","value":{"code":200,"data":{"required":false,"challenge":null,"responseSubmitted":false,"confirmed":false,"confirmationCode":"","skipHandoffUX":false,"error":""},"success":true}},"challenge_pending":{"summary":"Challenge waiting for the WebAuthn assertion","value":{"code":200,"data":{"required":true,"challenge":{"challenge":"ZmljdGl0aW91cy13ZWJhdXRobi1jaGFsbGVuZ2U","timeout":60000,"rpId":"whatsapp.com","allowCredentials":[{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","transports":["internal","hybrid"]}],"userVerification":"preferred","extensions":null},"responseSubmitted":false,"confirmed":false,"confirmationCode":"","skipHandoffUX":false,"error":""},"success":true}},"awaiting_confirmation":{"summary":"Response submitted, confirmation code received","value":{"code":200,"data":{"required":true,"challenge":{"challenge":"ZmljdGl0aW91cy13ZWJhdXRobi1jaGFsbGVuZ2U","timeout":60000,"rpId":"whatsapp.com","allowCredentials":[{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","transports":["internal","hybrid"]}],"userVerification":"preferred","extensions":null},"responseSubmitted":true,"confirmed":false,"confirmationCode":"482913","skipHandoffUX":false,"error":""},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/passkey/response":{"post":{"tags":["Session"],"summary":"Submit the WebAuthn passkey assertion","description":"Forwards the WebAuthn assertion produced by the user's authenticator to WhatsApp to continue passkey pairing.\n\nThe client must not build the `rpId` itself: it passes the `challenge` object from `GET /session/passkey/status` (which carries `rpId: whatsapp.com`) verbatim to `navigator.credentials.get()` and runs the ceremony only at the origin `https://web.whatsapp.com`.\n\n**Rules:**\n- Requires a client in memory (`500 no session`).\n- Rate limit: one submission per instance every 5 seconds (`429`). The limit is consumed before the body is validated, so a rejected body also starts the window.\n- Body capped at 256 KiB and decoded strictly: unknown fields or an oversized body return `400 invalid payload`.\n- Required: `id`, `rawId`, `type`, `response.clientDataJSON`, `response.authenticatorData`, `response.signature`; `response.userHandle` is optional.\n- `rawId` and every `response.*` value must be base64url without padding; `id` is forwarded as-is.\n- A rejection from WhatsApp returns `400` with the upstream error text (30-second timeout).\n- On success the state is marked `responseSubmitted`; poll the status for the confirmation code.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.PasskeyResponsePayload"},"examples":{"assertion":{"summary":"WebAuthn assertion without userHandle","description":"Values copied from `PublicKeyCredential` and re-encoded as base64url without padding.","value":{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","rawId":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","response":{"clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly93ZWIud2hhdHNhcHAuY29tIn0","authenticatorData":"ZmljdGl0aW91cy1hdXRoZW50aWNhdG9yLWRhdGE","signature":"ZmljdGl0aW91cy1zaWduYXR1cmUtYnl0ZXM"}}},"with_user_handle":{"summary":"Assertion including userHandle","description":"Discoverable credentials return a user handle; send it base64url-encoded when present.","value":{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","rawId":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","response":{"clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly93ZWIud2hhdHNhcHAuY29tIn0","authenticatorData":"ZmljdGl0aW91cy1hdXRoZW50aWNhdG9yLWRhdGE","signature":"ZmljdGl0aW91cy1zaWduYXR1cmUtYnl0ZXM","userHandle":"dXNlci1oYW5kbGUtMDAwMQ"}}}}}}},"responses":{"200":{"description":"Assertion accepted by WhatsApp; wait for the confirmation code.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeySubmitResponse"},"example":{"code":200,"data":{"status":"submitted","details":"Passkey response sent to WhatsApp. Await confirmation."},"success":true}}}},"400":{"description":"Bad Request: invalid or oversized body, missing field, value not base64url, or WhatsApp rejected the assertion.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Unknown field, invalid JSON or body over 256 KiB","value":{"code":400,"error":"invalid payload","success":false}},"missing_id":{"summary":"id missing","value":{"code":400,"error":"id is required","success":false}},"missing_signature":{"summary":"response.signature missing","value":{"code":400,"error":"response.signature is required","success":false}},"bad_raw_id":{"summary":"rawId is not base64url","value":{"code":400,"error":"invalid rawId: must be base64url","success":false}},"bad_user_handle":{"summary":"userHandle is not base64url","value":{"code":400,"error":"invalid userHandle: must be base64url","success":false}},"upstream_rejected":{"summary":"WhatsApp did not accept the assertion","value":{"code":400,"error":"info query returned status 401: not-authorized","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"description":"Too Many Requests: a submission was already made for this instance in the last 5 seconds.\n\n**Pela API pública:** Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":429,"error":"rate limit exceeded: try again in 5 seconds","success":false}},"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal Server Error: there is no client in memory; call `POST /session/connect` first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/passkey/confirm":{"post":{"tags":["Session"],"summary":"Confirm passkey pairing","description":"Tells WhatsApp that the user verified the passkey confirmation code on the phone, completing passkey pairing.\n\n**Rules:**\n- No request body is read.\n- Needed only when `GET /session/passkey/status` reports `skipHandoffUX: false`; with `skipHandoffUX: true` the gateway sends the confirmation automatically when the code arrives.\n- Requires a client in memory (`500 no session`).\n- A rejection from WhatsApp, or calling it before a response was submitted, returns `400` with the upstream error text (30-second timeout).\n- On success the passkey state is cleared; follow the `PairSuccess` event or `GET /session/status` until `loggedIn` is true.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Confirmation sent; pairing completes shortly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeyConfirmResponse"},"example":{"code":200,"data":{"status":"confirmed","details":"Passkey confirmation sent. Pairing should complete shortly."},"success":true}}}},"400":{"description":"Bad Request: WhatsApp rejected the confirmation, or no passkey response was submitted before.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_response_submitted":{"summary":"Confirm called before submitting the assertion","value":{"code":400,"error":"no passkey linking cache available","success":false}},"upstream_rejected":{"summary":"WhatsApp did not accept the confirmation","value":{"code":400,"error":"info query timed out","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/passkey/challenge":{"post":{"tags":["Session"],"summary":"Fetch the passkey challenge on demand","description":"Asks WhatsApp for the WebAuthn request options right away and stores them, so `GET /session/passkey/status` returns the challenge immediately instead of waiting for the `PasskeyRequest` event.\n\n**Rules:**\n- No request body is read. The instance must be connected (`POST /session/connect` first).\n- Without a client the call returns `500 no session`.\n- A disconnected client returns **503** `not_connected`; an account outside the passkey cohort (normal QR or phone-code accounts), or a refused request, returns **503** `passkey_unavailable` with the upstream reason. Fall back to `GET /session/qr` or `POST /session/pairphone` in that case.\n- Both 503 bodies keep the legacy envelope: `success: true` at the top level and `error`/`reason` inside `data`.\n- 30-second timeout for the WhatsApp request.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Challenge fetched and stored for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeyChallengeResponse"},"example":{"code":200,"data":{"required":true,"challenge":{"challenge":"ZmljdGl0aW91cy13ZWJhdXRobi1jaGFsbGVuZ2U","timeout":60000,"rpId":"whatsapp.com","allowCredentials":[{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","transports":["internal","hybrid"]}],"userVerification":"preferred","extensions":null}},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"description":"Service Unavailable (legacy envelope, `success: true`): the client is not connected, or passkey pairing is not available for this account.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SessionPasskeyUnavailableResponse"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"not_connected":{"summary":"Client is not connected","value":{"code":503,"data":{"error":"not_connected","reason":"connect the instance before probing the passkey challenge"},"success":true}},"passkey_unavailable":{"summary":"Account outside the passkey cohort","value":{"code":503,"data":{"error":"passkey_unavailable","reason":"info query returned status 404: item-not-found"},"success":true}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}}},"/session/connector/token":{"post":{"tags":["Connector"],"summary":"Mint an ephemeral Connector token","description":"Issues a short-lived token bound to this instance for the embeddable Connector widget, so the browser never receives the real instance token.\n\n**Rules:**\n- Call it from your backend with the real instance token; hand only `data.token` to the browser (for example `ZZ.connector.open({ token })`).\n- The token starts with `ct_`, lives for `CONNECTOR_TOKEN_TTL` seconds (default 600) and is accepted only on `/connector/*` routes, in the `token` header or the `token` query parameter.\n- Tokens are kept in memory: a gateway restart invalidates them.\n- Rate limit per real token: `CONNECTOR_TOKEN_RATE_PER_MIN` mints per minute (default 60); above it the call returns `429`.\n- No request body is read.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Ephemeral token issued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorTokenResponse"},"example":{"code":200,"data":{"token":"ct_Qm9ndXNFeGFtcGxlVG9rZW5WYWx1ZTAwMDAwMDAwMDAwMA","expiresIn":600,"tokenType":"connector"},"success":true}}}},"401":{"description":"Missing or invalid real instance token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"description":"Too Many Requests: the per-token mint limit for the current minute was reached.\n\n**Pela API pública:** Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":429,"error":"mint rate limit exceeded: try again shortly","success":false}},"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal Server Error: random bytes for the token could not be generated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"read /dev/urandom: resource temporarily unavailable","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/connect":{"post":{"tags":["Connector"],"summary":"[Connector] Connect the instance","description":"Browser-facing version of `POST /session/connect`: the embeddable widget starts the WhatsApp client with an ephemeral Connector token instead of the real instance token.\n\n**Rules:**\n- Authenticate with the `ct_...` token from `POST /session/connector/token` (header `token` or `?token=`); an unknown or expired token returns `401`.\n- Same body, side effects and errors as `POST /session/connect`: the body is required (send at least `{}`), `Subscribe` replaces the stored subscription and an omitted list clears it, and `Immediate: false` blocks for about 10 seconds.\n- Nothing is redacted: `data.webhook` and `data.jid` are returned to the browser. Prefer `Immediate: true` and poll `GET /connector/status`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Connect"},"examples":{"widget_immediate":{"summary":"Start pairing and return immediately","description":"The widget keeps the stored subscription it sends and polls the status afterwards.","value":{"Subscribe":["Message"],"Immediate":true}},"widget_wait":{"summary":"Wait up to 10 seconds for the socket","description":"Answers 500 `failed to connect` when the socket is not connected after the wait.","value":{"Subscribe":["All"],"Immediate":false}}}}}},"responses":{"200":{"description":"Client started for the instance bound to the Connector token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionConnectResponse"},"example":{"code":200,"data":{"details":"Connected!","events":"Message","jid":"","skip_media_download":false,"webhook":"https://example.com/webhook"},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the client is already connected, or the socket did not connect within the wait.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"already_connected":{"summary":"A connected client already exists","value":{"code":500,"error":"already connected","success":false}},"failed_to_connect":{"summary":"Socket not connected after the wait","value":{"code":500,"error":"failed to connect","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/disconnect":{"post":{"tags":["Connector"],"summary":"[Connector] Disconnect the instance","description":"Lets the Connector widget close the WhatsApp socket (for example when the user cancels pairing) without holding the real instance token.\n\n**Rules:**\n- Accepts only a valid, unexpired ephemeral token minted by `POST /session/connector/token`; otherwise `401`.\n- Runs the `POST /session/disconnect` handler: no body, `500 no session` without a client, a synthetic `Disconnected` webhook event when the client was connected or logged in.\n- The paired session is kept; the stored QR code is cleared.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Client disconnected; the paired session is kept.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionDisconnectResponse"},"example":{"code":200,"data":{"Details":"Disconnected successfully","wasConnected":true,"wasLoggedIn":false},"success":true}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for the instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/status":{"get":{"tags":["Connector"],"summary":"[Connector] Get the redacted connection status","description":"Returns the connection and pairing snapshot the widget needs to drive its UI, with every credential of the instance removed.\n\n**Rules:**\n- Requires the ephemeral `ct_...` token (header `token` or query `token`); the real instance token is rejected here with `401`.\n- Same snapshot as `GET /session/status` except that `token`, `webhook`, `events`, `proxy_url`, `proxy_config`, `s3_config` and `rabbitmq_config` are removed.\n- Use `connected`, `loggedIn`, `connectionHealth`, `qrcode` and the `passkey*` fields to decide which pairing step to show.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Redacted status snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorStatusResponse"},"example":{"code":200,"data":{"id":"bec45bb93cbd24cbec32941ec3c93a12","name":"Support Line","avatar_url":"","connected":true,"loggedIn":false,"hasClient":true,"connectionHealth":"connected_not_logged","lastSuccessfulConnect":1757862000,"autoReconnectErrors":0,"enableAutoReconnect":true,"expiration":86400,"jid":"","qrcode":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAA","skip_media_download":false,"skip_groups":false,"skip_newsletters":false,"skip_broadcasts":false,"skip_own_messages":false,"echo_api_messages":false,"skip_calls":false,"call_reject_message":"","call_reject_type":"","globalTransportSkips":{"skipGlobalWebhook":false,"skipGlobalRabbitMQ":false,"skipGlobalSQS":false,"skipGlobalRedis":false,"skipGlobalWebSocket":false,"skipGlobalS3":false},"isFromAPI":false,"auto_presence_unavailable":false,"passkeyRequired":false,"passkeyResponseSubmitted":false,"passkeyConfirmed":false,"passkeyConfirmationCode":"","passkeySkipHandoffUX":false,"passkeyError":"","timestamp":1757865600},"success":true}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the token lookup in the database failed, or the status could not be encoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"sql: database is closed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/qr":{"get":{"tags":["Connector"],"summary":"[Connector] Get the pairing QR code","description":"Returns the current pairing QR code so the widget can render it in the browser while the user scans it on the phone.\n\n**Rules:**\n- Authenticated by the short-lived Connector token only (header or query `token`); `401` once it expires.\n- Runs the `GET /session/qr` handler: the client must be connected and not logged in (`500 no session`, `500 not connected`, `500 already logged in`).\n- The code rotates every few seconds; poll it or follow `GET /connector/status` (`qrcode`).\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Current QR code (empty strings until the first code is generated).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionQRResponse"},"examples":{"qr_available":{"summary":"QR code ready to scan","value":{"code":200,"data":{"QRCode":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAA","code":"2@Xq3example0000QrTextValue,Zq9exampleNoiseKey=,Kp2exampleIdentityKey=,Tt5exampleAdvSecret=,1"},"success":true}},"not_generated_yet":{"summary":"Connected, first code not generated yet","value":{"code":200,"data":{"QRCode":"","code":""},"success":true}}}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no client, client not connected, instance already logged in, or the stored QR code could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No client in memory","value":{"code":500,"error":"no session","success":false}},"not_connected":{"summary":"Client exists but is not connected","value":{"code":500,"error":"not connected","success":false}},"already_logged_in":{"summary":"Instance is already paired","value":{"code":500,"error":"already logged in","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/pairphone":{"post":{"tags":["Connector"],"summary":"[Connector] Get a phone pairing code","description":"Requests a phone linking code from the widget, for users who pair by typing a code instead of scanning the QR.\n\n**Rules:**\n- Send the ephemeral token (not the real instance token) in the `token` header or query; expired tokens get `401`.\n- Same body, rules and errors as `POST /session/pairphone`: `Phone` required, optional case-insensitive `client_type` (default `chrome`), `400 already paired` for a paired instance and `500 no session` without a client.\n- WhatsApp rejections come back as `400` with the upstream text.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Pairphone"},"examples":{"default_chrome":{"summary":"Default device label","description":"Without `client_type` the phone shows \"Chrome (Linux)\".","value":{"Phone":"5511999999999"}},"macos_label":{"summary":"Show the code as a macOS device","description":"The phone lists the new linked device as \"macOS\".","value":{"Phone":"5511999999999","client_type":"macos"}}}}}},"responses":{"200":{"description":"Linking code generated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPairPhoneResponse"},"example":{"code":200,"data":{"LinkingCode":"9H3J-H3J8"},"success":true}}}},"400":{"description":"Bad Request: invalid body, missing `Phone`, unsupported `client_type`, instance already paired, or WhatsApp rejected the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone":{"summary":"Phone missing","value":{"code":400,"error":"missing Phone in Payload","success":false}},"invalid_client_type":{"summary":"Unsupported client_type","value":{"code":400,"error":"invalid client_type: accepted values are unknown, chrome, edge, firefox, ie, opera, safari, electron, uwp, otherwebclient, macos, android","success":false}},"already_paired":{"summary":"Instance is already paired","value":{"code":400,"error":"already paired","success":false}}}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory; connect first.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/passkey/status":{"get":{"tags":["Connector"],"summary":"[Connector] Get the passkey pairing state","description":"Returns the passkey pairing state to the widget, which runs the WebAuthn ceremony in the browser with the challenge it contains.\n\n**Rules:**\n- Auth: a `ct_...` Connector token that has not expired, in the `token` header or query; else `401`.\n- Same snapshot as `GET /session/passkey/status`; it holds no credentials, so nothing is redacted.\n- Pass `challenge` verbatim to `navigator.credentials.get({publicKey})` at the origin `https://web.whatsapp.com`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Passkey state snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeyStatusResponse"},"examples":{"idle":{"summary":"No passkey challenge pending","value":{"code":200,"data":{"required":false,"challenge":null,"responseSubmitted":false,"confirmed":false,"confirmationCode":"","skipHandoffUX":false,"error":""},"success":true}},"challenge_pending":{"summary":"Challenge waiting for the WebAuthn assertion","value":{"code":200,"data":{"required":true,"challenge":{"challenge":"ZmljdGl0aW91cy13ZWJhdXRobi1jaGFsbGVuZ2U","timeout":60000,"rpId":"whatsapp.com","allowCredentials":[{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","transports":["internal","hybrid"]}],"userVerification":"preferred","extensions":null},"responseSubmitted":false,"confirmed":false,"confirmationCode":"","skipHandoffUX":false,"error":""},"success":true}}}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/passkey/challenge":{"post":{"tags":["Connector"],"summary":"[Connector] Fetch the passkey challenge on demand","description":"Lets the widget force WhatsApp to issue the WebAuthn challenge immediately, so the passkey tab does not wait for the reactive `PasskeyRequest` event.\n\n**Rules:**\n- The ephemeral token minted for this instance is the only accepted credential (header or query `token`); `401` otherwise.\n- Runs the `POST /session/passkey/challenge` handler: no body, the instance must be connected.\n- **503** bodies (`not_connected`, `passkey_unavailable`) keep the legacy envelope with `success: true`; on `passkey_unavailable` the widget should switch to the QR or phone-code tab.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Challenge fetched and stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeyChallengeResponse"},"example":{"code":200,"data":{"required":true,"challenge":{"challenge":"ZmljdGl0aW91cy13ZWJhdXRobi1jaGFsbGVuZ2U","timeout":60000,"rpId":"whatsapp.com","allowCredentials":[{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","transports":["internal","hybrid"]}],"userVerification":"preferred","extensions":null}},"success":true}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for the instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"description":"Service Unavailable (legacy envelope, `success: true`): client not connected, or passkey pairing not available for the account.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SessionPasskeyUnavailableResponse"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"not_connected":{"summary":"Client is not connected","value":{"code":503,"data":{"error":"not_connected","reason":"connect the instance before probing the passkey challenge"},"success":true}},"passkey_unavailable":{"summary":"Account outside the passkey cohort","value":{"code":503,"data":{"error":"passkey_unavailable","reason":"info query returned status 404: item-not-found"},"success":true}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}}},"/connector/passkey/response":{"post":{"tags":["Connector"],"summary":"[Connector] Submit the WebAuthn passkey assertion","description":"Receives the assertion that the browser obtained from `navigator.credentials.get()` and forwards it to WhatsApp on behalf of the widget.\n\n**Rules:**\n- Use the Connector token issued by your backend (header or query `token`); a missing or expired one is answered with `401`.\n- Same strict body and errors as `POST /session/passkey/response`: 256 KiB cap, unknown fields rejected, base64url without padding for `rawId` and `response.*`, one submission every 5 seconds (`429`).\n- After `200`, poll `GET /connector/passkey/status` for the confirmation code.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.PasskeyResponsePayload"},"examples":{"assertion":{"summary":"WebAuthn assertion without userHandle","description":"Binary values from `PublicKeyCredential` re-encoded as base64url without padding.","value":{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","rawId":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","response":{"clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly93ZWIud2hhdHNhcHAuY29tIn0","authenticatorData":"ZmljdGl0aW91cy1hdXRoZW50aWNhdG9yLWRhdGE","signature":"ZmljdGl0aW91cy1zaWduYXR1cmUtYnl0ZXM"}}},"with_user_handle":{"summary":"Assertion including userHandle","description":"Send `userHandle` when the authenticator returns one.","value":{"id":"Y3JlZGVudGlhbC1pZC0wMDAx","rawId":"Y3JlZGVudGlhbC1pZC0wMDAx","type":"public-key","response":{"clientDataJSON":"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly93ZWIud2hhdHNhcHAuY29tIn0","authenticatorData":"ZmljdGl0aW91cy1hdXRoZW50aWNhdG9yLWRhdGE","signature":"ZmljdGl0aW91cy1zaWduYXR1cmUtYnl0ZXM","userHandle":"dXNlci1oYW5kbGUtMDAwMQ"}}}}}}},"responses":{"200":{"description":"Assertion accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeySubmitResponse"},"example":{"code":200,"data":{"status":"submitted","details":"Passkey response sent to WhatsApp. Await confirmation."},"success":true}}}},"400":{"description":"Bad Request: invalid or oversized body, missing field, value not base64url, or WhatsApp rejected the assertion.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Unknown field, invalid JSON or body over 256 KiB","value":{"code":400,"error":"invalid payload","success":false}},"missing_type":{"summary":"type missing","value":{"code":400,"error":"type is required","success":false}},"bad_signature":{"summary":"signature is not base64url","value":{"code":400,"error":"invalid signature: must be base64url","success":false}},"upstream_rejected":{"summary":"WhatsApp did not accept the assertion","value":{"code":400,"error":"info query returned status 401: not-authorized","success":false}}}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"description":"Too Many Requests: a submission was already made for this instance in the last 5 seconds.\n\n**Pela API pública:** Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":429,"error":"rate limit exceeded: try again in 5 seconds","success":false}},"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}},"500":{"description":"Internal Server Error: there is no client in memory for the instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/connector/passkey/confirm":{"post":{"tags":["Connector"],"summary":"[Connector] Confirm passkey pairing","description":"Sends the final passkey confirmation from the widget after the user compared the confirmation code on the phone.\n\n**Rules:**\n- Authorized by the ephemeral Connector token (header or query `token`), never by the real instance token; `401` when it is not valid.\n- Needed only when the status reports `skipHandoffUX: false`; otherwise the gateway already confirmed.\n- Runs the `POST /session/passkey/confirm` handler: no body, `400` with the upstream text when WhatsApp refuses, `500 no session` without a client.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Confirmation sent; pairing completes shortly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPasskeyConfirmResponse"},"example":{"code":200,"data":{"status":"confirmed","details":"Passkey confirmation sent. Pairing should complete shortly."},"success":true}}}},"400":{"description":"Bad Request: WhatsApp rejected the confirmation, or no passkey response was submitted before.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_response_submitted":{"summary":"Confirm called before submitting the assertion","value":{"code":400,"error":"no passkey linking cache available","success":false}},"key_not_ready":{"summary":"Confirmation code not received yet","value":{"code":400,"error":"passkey linking cache does not have an encryption key yet","success":false}}}}}},"401":{"description":"Connector token missing, unknown or expired (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: there is no client in memory for the instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/import":{"post":{"tags":["Session"],"summary":"Import an existing web.whatsapp.com session (BETA)","description":"Converts a web.whatsapp.com device identity into a native device of this instance and boots it, as an alternative to QR, phone-code or passkey pairing. The payload is impersonation-grade key material: guard this endpoint and never log the body.\n\n**Rules:**\n- Body up to 16 MiB. A body with `meJid` is parsed as a structured `WebDeviceSnapshot`; a body with `source: wa-web` or an `indexeddb` object is treated as a generic companion dump; anything else returns `400`.\n- Structured snapshot, required: `meJid`, non-zero `registrationId`, `noiseKey.priv`, `identityKey.priv`, `signedPreKey.priv` (32 bytes), `signedPreKey.signature` (64 bytes) and the four `account` fields. Key material is base64 (standard or URL alphabet, padded or not); `pub` values are ignored because they are derived from `priv`.\n- Optional: `lid`, `advSecretKey` (a random key is kept when omitted), `platform`, `pushName`, `businessName`.\n- Invalid key material returns `422 snapshot conversion failed: ...`.\n- **Generic dump:** automatic extraction is not implemented yet, so a dump is always answered with `422` listing the missing fields (legacy envelope, `success: true`). Nothing is fabricated.\n- On success the device is stored, `users.jid` is updated and the client starts in the background with the `Message` subscription only. Poll `GET /session/status` until `loggedIn` is true and call `POST /session/connect` to set the subscription you need.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.WebDeviceSnapshot"},"examples":{"structured_snapshot":{"summary":"Structured snapshot with every field","description":"All key material in base64. The values are synthetic and do not open a real session.","value":{"meJid":"5511999999999:12@s.whatsapp.net","lid":"123456789012345:12@lid","registrationId":12345,"noiseKey":{"priv":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="},"identityKey":{"priv":"ISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0A="},"signedPreKey":{"keyId":1,"priv":"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2A=","signature":"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foA=="},"account":{"details":"CwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6","accountSignature":"FRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVA==","accountSignatureKey":"HyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4=","deviceSignature":"KSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaA=="},"advSecretKey":"MzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVI=","platform":"chrome","pushName":"Support Line","businessName":""}},"minimal_snapshot":{"summary":"Only the required fields","description":"Without `advSecretKey` a fresh random ADV secret is kept; `lid`, `platform` and names stay empty.","value":{"meJid":"5511999999999:12@s.whatsapp.net","registrationId":12345,"noiseKey":{"priv":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="},"identityKey":{"priv":"ISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0A="},"signedPreKey":{"keyId":1,"priv":"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2A=","signature":"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foA=="},"account":{"details":"CwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6","accountSignature":"FRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVA==","accountSignatureKey":"HyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4=","deviceSignature":"KSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaA=="}}},"wa_web_dump":{"summary":"Generic companion dump (always answered with 422)","description":"Recognized by `source` or `indexeddb`; the extractor reports the identity fields it cannot resolve.","value":{"source":"wa-web","indexeddb":{"wawc":{}}}}}}}},"responses":{"200":{"description":"Device stored; the client is booting in the background.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionImportResponse"},"example":{"code":200,"data":{"status":"imported","jid":"5511999999999:12@s.whatsapp.net","note":"device booting (BETA); poll /session/status for loggedIn"},"success":true}}}},"400":{"description":"Bad Request: the body could not be read (or exceeds 16 MiB), is not JSON, or matches neither accepted shape.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_body":{"summary":"Body unreadable or over 16 MiB","value":{"code":400,"error":"could not read body","success":false}},"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid JSON","success":false}},"invalid_snapshot":{"summary":"meJid present but a field has the wrong type","value":{"code":400,"error":"invalid snapshot","success":false}},"unrecognized_payload":{"summary":"Neither a snapshot nor a wa-web dump","value":{"code":400,"error":"unrecognized import payload: expected a WebDeviceSnapshot or a wa-web dump","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"422":{"description":"Unprocessable Entity: the snapshot key material is invalid (error envelope), or a generic dump could not be converted (legacy envelope with `success: true` and details in `data`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionImportUnprocessableResponse"},"examples":{"conversion_failed":{"summary":"Invalid key material in the snapshot","value":{"code":422,"error":"snapshot conversion failed: noiseKey: priv: expected 32 bytes, got 16","success":false}},"missing_registration_id":{"summary":"registrationId missing or zero","value":{"code":422,"error":"snapshot conversion failed: registrationId is required and must be non-zero","success":false}},"incomplete_dump":{"summary":"Generic dump without resolvable identity fields","value":{"code":422,"data":{"error":"incomplete wa-web dump: auto-extraction could not resolve required fields","missing":["meJid","registrationId","noiseKey","identityKey","signedPreKey","account"],"hint":"supply a structured WebDeviceSnapshot (meJid, registrationId, noiseKey, identityKey, signedPreKey, account) — see docs/session-import.md"},"success":true}}}}}},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the device store is not initialized, or the device could not be persisted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"container_not_initialized":{"summary":"Device store not initialized","value":{"code":500,"error":"whatsmeow container not initialized","success":false}},"persist_failed":{"summary":"Device could not be stored","value":{"code":500,"error":"persist device: sql: database is closed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/qr":{"get":{"tags":["Session"],"summary":"Get the pairing QR code","description":"Returns the current pairing QR code of a connected instance that is not logged in yet, as a PNG data URL and as the raw code text.\n\n**Rules:**\n- Call `POST /session/connect` first. Without a client the call returns `500 no session`; with a disconnected client `500 not connected`.\n- A logged-in instance returns `500 already logged in`.\n- WhatsApp rotates the code every few seconds; poll this endpoint or subscribe to the `QR` event instead of caching it.\n- Right after connecting, before the first code is generated, both fields can be empty strings.\n- `code` is the raw text encoded in the QR image, useful for rendering the QR yourself.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Current QR code (empty strings until the first code is generated).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionQRResponse"},"examples":{"qr_available":{"summary":"QR code ready to scan","value":{"code":200,"data":{"QRCode":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAA","code":"2@Xq3example0000QrTextValue,Zq9exampleNoiseKey=,Kp2exampleIdentityKey=,Tt5exampleAdvSecret=,1"},"success":true}},"not_generated_yet":{"summary":"Connected, first code not generated yet","value":{"code":200,"data":{"QRCode":"","code":""},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no client, client not connected, instance already logged in, or the stored QR code could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No client in memory","value":{"code":500,"error":"no session","success":false}},"not_connected":{"summary":"Client exists but is not connected","value":{"code":500,"error":"not connected","success":false}},"already_logged_in":{"summary":"Instance is already paired","value":{"code":500,"error":"already logged in","success":false}},"database_error":{"summary":"Stored QR code could not be read","value":{"code":500,"error":"sql: database is closed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/network-route":{"post":{"tags":["Session Network Route"],"summary":"Provision or update the mobile network route","operationId":"applySessionNetworkRoute","description":"Provisions an isolated `tsnet` node for this session that egresses through a stable Tailscale exit node (typically a phone on mobile data), then reconnects the WhatsApp client through it.\n\n**Features:**\n- The current client is disconnected before the route is prepared; the node starts, selects the exit node, opens an authenticated SOCKS5 listener on `127.0.0.1` and runs a SOCKS/TLS preflight.\n- When the client was connected before and the route becomes ready, a reconnect is scheduled (`reconnectScheduled: true`).\n- `authKey` is write-only: used once during node start, never persisted, returned or logged.\n\n**Rules:**\n- Strict body: unknown fields or invalid JSON return `400 network_route_payload_invalid`.\n- `mode` must be `mobile` and `tcpOnly` must be `true`; native Calls/UDP stay disabled while the route exists.\n- `failClosed` is a plain boolean and **omitting it means `false`**: while the route is not ready the session may leave through the default egress (legacy proxy or direct). Send `true` to hold traffic instead.\n- `exitNodeId`: 3-128 characters `[A-Za-z0-9_-]`. `idempotencyKey`: 8-160 characters `[A-Za-z0-9._:-]`. `authKey`: 12-512 printable characters starting with `tskey-auth-`.\n- `routeVersion` is a fencing token (>= 1). A lower version returns `409 network_route_stale_version`; the same version with a different configuration or key returns `409 network_route_version_conflict`; an exact retry returns the current state (200 when ready, 503 with the stored error code when not).\n- A failed start leaves the route `blocked` (`503 network_route_prepare_failed`, redacted cause in `details`). Retry with a higher `routeVersion` and a new one-use auth key, or remove the route.\n- Error bodies raised by the route manager also carry `data` with the route state; for validation errors that state is empty.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.NetworkRouteRequest"},"examples":{"first_apply_fail_closed":{"summary":"First route, hold traffic while not ready","description":"Version 1 with `failClosed` true, so nothing leaves through another IP while the exit node is unavailable.","value":{"mode":"mobile","authKey":"tskey-auth-kExample0000CNTRL-ExampleSecretValue0000","exitNodeId":"nStableMobileExit01","routeVersion":1,"idempotencyKey":"route-2026-09-15-0001","failClosed":true,"tcpOnly":true}},"new_version_fail_open":{"summary":"New version that falls back to the default egress","description":"A higher `routeVersion` with a new auth key; omitting `failClosed` would have the same fail-open effect as `false`.","value":{"mode":"mobile","authKey":"tskey-auth-kExample0001CNTRL-ExampleSecretValue0001","exitNodeId":"nStableMobileExit02","routeVersion":2,"idempotencyKey":"route-2026-09-15-0002","failClosed":false,"tcpOnly":true}}}}}},"responses":{"200":{"description":"Route ready, or an exact retry of the current version that is already ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteApplyResponse"},"examples":{"ready_reconnect":{"summary":"Route ready, client reconnect scheduled","value":{"code":200,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":1,"appliedVersion":1,"failClosed":true,"tcpOnly":true,"status":"ready","ready":true},"details":"network route ready","reconnectScheduled":true,"success":true}},"idempotent_retry":{"summary":"Exact retry of the ready version","value":{"code":200,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":1,"appliedVersion":1,"failClosed":true,"tcpOnly":true,"status":"ready","ready":true},"details":"network route ready","reconnectScheduled":false,"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON or unknown field, or a field failed validation. Validation errors carry an empty `data` route state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},"examples":{"payload_invalid":{"summary":"Invalid JSON or unknown field","value":{"code":400,"error":"network_route_payload_invalid","success":false}},"tcp_only_required":{"summary":"tcpOnly is not true","value":{"code":400,"data":{"mode":"","exitNodeId":"","desiredVersion":0,"appliedVersion":0,"failClosed":false,"tcpOnly":false,"status":"","ready":false},"error":"network_route_mobile_requires_tcp_only","success":false}},"auth_key_invalid":{"summary":"authKey missing or malformed","value":{"code":400,"data":{"mode":"","exitNodeId":"","desiredVersion":0,"appliedVersion":0,"failClosed":false,"tcpOnly":false,"status":"","ready":false},"error":"network_route_auth_key_invalid","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: fencing or idempotency violation; the stored route is not changed. `data` holds the stored route.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},"examples":{"stale_version":{"summary":"routeVersion lower than the stored version","value":{"code":409,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":3,"appliedVersion":3,"failClosed":true,"tcpOnly":true,"status":"ready","ready":true},"error":"network_route_stale_version","success":false}},"version_conflict":{"summary":"Same version, different configuration or idempotency key","value":{"code":409,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":3,"appliedVersion":3,"failClosed":true,"tcpOnly":true,"status":"ready","ready":true},"error":"network_route_version_conflict","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"description":"Service Unavailable: route manager or store unavailable, the client could not be stopped, the node failed to start (route left `blocked`), or an exact retry of a version that is not ready.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"prepare_failed":{"summary":"Node start or preflight failed; route blocked","value":{"code":503,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":2,"appliedVersion":1,"failClosed":true,"tcpOnly":true,"status":"blocked","ready":false,"errorCode":"network_route_prepare_failed"},"details":"exit node nStableMobileExit01 is offline","error":"network_route_prepare_failed","success":false}},"manager_unavailable":{"summary":"Route manager not initialized in this process","value":{"code":503,"error":"network_route_manager_unavailable","success":false}},"not_ready_retry":{"summary":"Exact retry of a blocked version","value":{"code":503,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":2,"appliedVersion":1,"failClosed":true,"tcpOnly":true,"status":"blocked","ready":false,"errorCode":"network_route_prepare_failed"},"error":"network_route_prepare_failed","success":false}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}},"get":{"tags":["Session Network Route"],"summary":"Get the mobile network route state","operationId":"getSessionNetworkRoute","description":"Returns the non-secret state of this session's mobile route: desired and applied versions, fail mode, status and live readiness. With `probe=egress` it also proves the public IP the route really exits from.\n\n**Rules:**\n- Never returns the auth key, SOCKS credentials, proxy URL or state paths.\n- `ready: true` requires `status: ready`, `desiredVersion == appliedVersion` and a live node for that version in this process; after a gateway restart it stays false until the node is restored.\n- `probe=egress` makes a real external request through the route (10-second timeout) and adds `egressIP` at the top level. When the probe fails the call still answers 200 with `egressProbeError` instead. Any other `probe` value is ignored.\n- `404 network_route_not_configured` when the session has no route.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"in":"query","name":"probe","required":false,"description":"Send `egress` to measure the route's real public exit IP (external request). Other values only return the stored state.","schema":{"type":"string","enum":["egress"]},"example":"egress"}],"responses":{"200":{"description":"Route state, plus `egressIP` or `egressProbeError` when `probe=egress`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteGetResponse"},"examples":{"state":{"summary":"Route state without probe","value":{"code":200,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":3,"appliedVersion":3,"failClosed":true,"tcpOnly":true,"status":"ready","ready":true},"success":true}},"egress_probe":{"summary":"probe=egress succeeded","value":{"code":200,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":3,"appliedVersion":3,"failClosed":true,"tcpOnly":true,"status":"ready","ready":true},"egressIP":"203.0.113.45","success":true}},"egress_probe_failed":{"summary":"probe=egress failed (route not active)","value":{"code":200,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":2,"appliedVersion":1,"failClosed":true,"tcpOnly":true,"status":"blocked","ready":false,"errorCode":"network_route_prepare_failed"},"egressProbeError":"network_route_egress_probe_failed","success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no mobile route is configured for this session.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},"example":{"code":404,"error":"network_route_not_configured","success":false}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"description":"Service Unavailable: the route manager is not initialized, or the route metadata could not be read.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"manager_unavailable":{"summary":"Route manager not initialized","value":{"code":503,"error":"network_route_manager_unavailable","success":false}},"store_unavailable":{"summary":"Route metadata unreadable","value":{"code":503,"error":"network_route_store_unavailable","success":false}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}},"delete":{"tags":["Session Network Route"],"summary":"Remove the mobile network route","operationId":"removeSessionNetworkRoute","description":"Removes this session's mobile route on explicit operator request: the live node is logged out and closed, the stored row and the node state kept in the database are deleted, and any legacy state file is wiped. Afterwards the session egresses through its legacy `proxy_url`, or directly when none is set, so the peer sees a different IP.\n\n**Rules:**\n- No body. The client is disconnected first and any stored QR code is cleared.\n- `data` is the route as read right before removal.\n- A reconnect is scheduled (`reconnectScheduled: true`) when the client was connected, or when a fail-closed route that was not ready had been holding the session offline, so a fresh QR code is produced. A session stopped on purpose over a healthy route stays stopped.\n- Idempotent by absence: a second call returns `404 network_route_not_configured`.\n- `503 network_route_revoke_failed` may leave a partial removal; repeat the call, and a `404` then confirms the route is gone.\n- The next apply accepts any valid `routeVersion` and needs a new one-use auth key.\n\n**Use Cases:**\n- Unblock a session held offline by a route that will not converge (`status: blocked`)\n- Recover after the route runtime did not come back from a gateway restart\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Route removed; `data` is its last state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteApplyResponse"},"example":{"code":200,"data":{"mode":"mobile","exitNodeId":"nStableMobileExit01","desiredVersion":4,"appliedVersion":3,"failClosed":true,"tcpOnly":true,"status":"blocked","ready":false,"errorCode":"network_route_prepare_failed"},"details":"network route removed; this session egresses through its legacy proxy_url on the next connect, or directly when none is set","reconnectScheduled":true,"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no route is configured (also the answer to a repeated removal).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},"example":{"code":404,"error":"network_route_not_configured","success":false}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"description":"Service Unavailable: route manager not initialized, metadata unreadable, or the removal failed.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/NetworkRouteErrorResponse"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"manager_unavailable":{"summary":"Route manager not initialized","value":{"code":503,"error":"network_route_manager_unavailable","success":false}},"store_unavailable":{"summary":"Route metadata unreadable","value":{"code":503,"error":"network_route_store_unavailable","success":false}},"revoke_failed":{"summary":"Node close, row delete or cleanup failed","value":{"code":503,"error":"network_route_revoke_failed","success":false}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}}},"/session/proxy":{"post":{"tags":["Session"],"summary":"Set or remove the connection proxy","description":"Stores or removes the legacy proxy used by the WhatsApp connection of this instance (`users.proxy_url`). The proxy is applied on the next connect.\n\n**Rules:**\n- The instance must be **disconnected**: a connected client returns `400 cannot set proxy while connected. Please disconnect first` before the body is read.\n- `enable: false` (or omitted) removes the proxy and ignores `proxy_url`.\n- `enable: true` requires `proxy_url` with scheme `http`, `https` or `socks5`, for example `socks5://user:pass@host:1080`.\n- The URL is stored as given (credentials included) and echoed in `data.ProxyURL`.\n- `RequiresReconnection` and `Message` exist for a connected client, but connected clients are rejected up front, so `RequiresReconnection` is `false` in practice.\n- A session with a mobile network route (`/session/network-route`) egresses through that route instead of this proxy.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionProxyRequest"},"examples":{"socks5":{"summary":"Enable a SOCKS5 proxy with credentials","description":"Stores the SOCKS5 URL; it is used on the next `POST /session/connect`.","value":{"enable":true,"proxy_url":"socks5://proxyuser:proxypass@proxy.example.com:1080"}},"http":{"summary":"Enable an HTTP proxy","description":"HTTP and HTTPS proxies are accepted as well.","value":{"enable":true,"proxy_url":"http://proxy.example.com:3128"}},"disable":{"summary":"Remove the proxy","description":"Clears the stored proxy; the next connect goes out directly.","value":{"enable":false}}}}}},"responses":{"200":{"description":"Proxy stored or removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionProxyResponse"},"examples":{"enabled":{"summary":"Proxy stored","value":{"code":200,"data":{"Details":"Proxy configured successfully","ProxyURL":"socks5://proxyuser:proxypass@proxy.example.com:1080","RequiresReconnection":false},"success":true}},"disabled":{"summary":"Proxy removed","value":{"code":200,"data":{"Details":"Proxy disabled successfully","RequiresReconnection":false},"success":true}}}}}},"400":{"description":"Bad Request: client connected, invalid body, missing or malformed `proxy_url`, or unsupported scheme.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"connected":{"summary":"Client is connected","value":{"code":400,"error":"cannot set proxy while connected. Please disconnect first","success":false}},"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_proxy_url":{"summary":"enable is true but proxy_url is empty","value":{"code":400,"error":"missing proxy_url in payload","success":false}},"invalid_format":{"summary":"proxy_url cannot be parsed","value":{"code":400,"error":"invalid proxy URL format","success":false}},"unsupported_scheme":{"summary":"Scheme other than http, https or socks5","value":{"code":400,"error":"only HTTP, HTTPS and SOCKS5 proxies are supported","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the proxy could not be written to the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"save_failed":{"summary":"Proxy could not be stored","value":{"code":500,"error":"failed to save proxy configuration","success":false}},"remove_failed":{"summary":"Proxy could not be removed","value":{"code":500,"error":"failed to remove proxy configuration","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/s3/config":{"post":{"tags":["Session S3"],"summary":"Configure S3 storage for this instance","description":"Stores the per-instance S3-compatible storage (AWS S3, MinIO, Backblaze B2, Cloudflare R2, etc.) used to upload\nmedia from incoming and outgoing messages, and chooses how that media is delivered inside events.\n\n**Rules:**\n- **Full replace:** every call overwrites all S3 columns. Omitted fields are stored empty, `false` or `0`, so always send the complete configuration.\n- `media_delivery` accepts `base64`, `s3`, `url` (alias, stored as `s3`) or `both`. Empty or omitted is stored as `base64`; any other value returns **400**.\n- `retention_days: 0` disables object expiration.\n- No connectivity or credential check happens here. Use `POST /session/s3/test` after saving.\n- `enabled: false` keeps the other values as sent but stops uploads for this instance.\n\n**Side effects:**\n- The user configuration cache is reloaded and the S3 client of the instance is rebuilt from the saved values.\n\n**Use Cases:**\n- Deliver media as short URLs instead of large base64 blobs in webhooks\n- Keep a copy of every media file in your own bucket with an expiration policy\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionS3ConfigRequest"},"examples":{"aws_s3":{"summary":"AWS S3 with bucket owner enforced ownership","description":"Standard AWS endpoint (leave `endpoint` empty), ACLs disabled, media delivered as both URL and base64, objects kept for 30 days.","value":{"enabled":true,"endpoint":"","region":"us-east-1","bucket":"zigzapy-media-example","access_key":"AKIAIOSFODNN7EXAMPLE","secret_key":"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY","path_style":false,"public_url":"","media_delivery":"both","retention_days":30,"disable_acl":true}},"minio_cdn":{"summary":"MinIO with path-style addressing and a CDN URL","description":"Self-hosted MinIO requires `path_style`. Links in events use `public_url` as the base and objects never expire.","value":{"enabled":true,"endpoint":"https://minio.example.com","region":"us-east-1","bucket":"whatsapp-media","access_key":"minio-access-example","secret_key":"minio-secret-example","path_style":true,"public_url":"https://cdn.example.com","media_delivery":"url","retention_days":0,"disable_acl":false}},"disable":{"summary":"Disable S3 uploads","description":"Because the call is a full replace, every other S3 field is stored empty and media delivery falls back to `base64`.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"S3 configuration saved and the S3 client rebuilt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionS3ConfigSaveResponse"},"example":{"code":200,"data":{"Details":"S3 configuration saved successfully","Enabled":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `media_delivery` is not an accepted value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"invalid_media_delivery":{"summary":"media_delivery is not base64, s3, url or both","value":{"code":400,"error":"media_delivery must be 'base64', 's3', 'url', or 'both'","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the database update failed, or the cache/S3 client could not be rebuilt from the saved values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"save_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to save S3 configuration","success":false}},"cache_failed":{"summary":"Cache reload or S3 client rebuild failed","value":{"code":500,"error":"failed to update S3 cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session S3"],"summary":"Get the S3 storage configuration","description":"Returns the S3 storage configuration stored for this instance, as used for media uploads and media delivery in events.\n\n**Rules:**\n- `secret_key` is never returned.\n- `access_key` is always returned as `***`, even when no key is stored.\n- Values are read from the database, so this reflects the last `POST /session/s3/config` or `DELETE /session/s3/config`, not a connectivity check.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored S3 configuration with the access key masked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionS3ConfigGetResponse"},"examples":{"configured":{"summary":"S3 configured","value":{"code":200,"data":{"enabled":true,"endpoint":"https://minio.example.com","region":"us-east-1","bucket":"whatsapp-media","access_key":"***","path_style":true,"public_url":"https://cdn.example.com","media_delivery":"s3","retention_days":30,"disable_acl":false},"success":true}},"not_configured":{"summary":"S3 never configured or deleted","value":{"code":200,"data":{"enabled":false,"endpoint":"","region":"","bucket":"","access_key":"***","path_style":true,"public_url":"","media_delivery":"base64","retention_days":30,"disable_acl":false},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get S3 configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"delete":{"tags":["Session S3"],"summary":"Delete the S3 storage configuration","description":"Removes the S3 storage configuration of this instance and returns media delivery to inline `base64`.\n\n**Rules:**\n- Stores `enabled=false`, empty endpoint, region, bucket, keys and public URL, `path_style=true`, `media_delivery=base64` and `retention_days=30`.\n- `disable_acl` is not reset and keeps its previous value.\n- Objects already uploaded to the bucket are not deleted.\n- The user configuration cache is reloaded and the instance S3 client is removed.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"S3 configuration removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionS3ConfigDeleteResponse"},"example":{"code":200,"data":{"Details":"S3 configuration deleted successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the database update failed, or the cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"delete_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to delete S3 configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update S3 cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/s3/test":{"post":{"tags":["Session S3"],"summary":"Test the stored S3 connection","description":"Verifies that the stored S3 configuration can reach the bucket, by rebuilding the S3 client and listing at most one object.\n\n**Rules:**\n- No request body: the test always uses the configuration saved with `POST /session/s3/config`.\n- Fails with **400** when S3 is disabled for this instance.\n- The bucket listing has a 10 second timeout; nothing is uploaded or deleted.\n- A successful test also leaves the rebuilt S3 client active for uploads.\n\n**Use Cases:**\n- Validate credentials, endpoint and bucket permissions right after saving them\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Bucket reachable with the stored credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionS3TestResponse"},"example":{"code":200,"data":{"Details":"S3 connection test successful","Bucket":"whatsapp-media","Region":"us-east-1"},"success":true}}}},"400":{"description":"Bad Request: S3 is not enabled for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"S3 is not enabled for this user","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration could not be read, the S3 client could not be built, or the bucket listing failed (credentials, permissions, endpoint or network).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"read_failed":{"summary":"Configuration could not be read","value":{"code":500,"error":"failed to get S3 configuration","success":false}},"client_failed":{"summary":"S3 client could not be built","value":{"code":500,"error":"failed to initialize S3 client: failed to load AWS configuration","success":false}},"access_denied":{"summary":"Bucket listing rejected","value":{"code":500,"error":"S3 connection test failed: operation error S3: ListObjectsV2, https response error StatusCode: 403, api error AccessDenied: Access Denied","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/rabbitmq/config":{"post":{"tags":["Session RabbitMQ"],"summary":"Configure the RabbitMQ publisher for this instance","description":"Stores the per-instance RabbitMQ publisher that receives WhatsApp events, including exchange and queue topology,\ndead-lettering, queue limits and publisher tuning.\n\n**Rules:**\n- **Full replace:** every call overwrites all RabbitMQ columns. Omitted fields are stored as `false`, empty or NULL (server defaults), so always send the complete configuration.\n- `events` is a comma-separated list of canonical, case-sensitive event names or `All`. Spaces around names are trimmed and empty items skipped; an unknown name returns **400**. Empty means no events.\n- When `enabled` is `true`: `exchange_type` defaults to `topic`, `queue_type` to `classic` and `routing_key` to `events.#`. O exchange e a fila padrão derivam do ID da instância; consulte `GET /session/rabbitmq/config`. `exchange_type` and `queue_type` are only validated in this case.\n- `delivery_mode` `0` or omitted is stored as `2` (persistent).\n- `connection_pool_size`, `worker_count`, `queue_buffer_size`, `batch_size` and `publish_timeout_ms` must be greater than 0; `batch_timeout_ms`, `max_retries` and `retry_delay_ms` must be non-negative.\n- `queue_arguments` and `exchange_arguments` are **JSON-encoded strings**. Sending a JSON object in these fields fails with `400 could not decode payload`.\n- The broker is not contacted here: a wrong URL does not fail this request. Use `POST /session/rabbitmq/test`.\n\n**Features:**\n- **Dynamic queues:** `{user_id}` and `{event_type}` placeholders in `queue` and `routing_key` are expanded per event; a `queue` containing `{event_type}` creates one queue per event type.\n- **Dead-lettering and limits:** `dead_letter_exchange`, `dead_letter_routing_key`, `message_ttl`, `max_length` and `max_length_bytes` become `x-*` queue arguments.\n- **Transport registration:** enabling registers the individual RabbitMQ transport in the event dispatcher; disabling unregisters it.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRabbitMQConfigRequest"},"examples":{"minimal":{"summary":"Enable with server defaults","description":"Only the URL and events are sent; exchange, queue, routing key, exchange type and queue type get their defaults.","value":{"enabled":true,"url":"amqp://zzg_user:zzg_pass@rabbitmq.example.com:5672/","events":"All"}},"dynamic_quorum_dlx":{"summary":"Per-event quorum queues with dead-lettering and tuning","description":"One quorum queue per event type, a dead-letter exchange, a 24 hour message TTL, overflow rejection and custom publisher tuning.","value":{"enabled":true,"url":"amqps://zzg_user:zzg_pass@rabbitmq.example.com:5671/whatsapp","exchange":"whatsapp.events","exchange_type":"topic","queue":"user_{user_id}_event_{event_type}","queue_type":"quorum","routing_key":"whatsapp.{user_id}.{event_type}","events":"Message,ReadReceipt,Connected","durable":true,"auto_delete":false,"exclusive":false,"no_wait":false,"delivery_mode":2,"dead_letter_exchange":"dlx.zigzapy","dead_letter_routing_key":"dlq.events","message_ttl":86400000,"max_length":100000,"max_length_bytes":104857600,"queue_arguments":"{\"x-overflow\":\"reject-publish\"}","exchange_arguments":"{}","worker_count":50,"batch_size":500,"batch_timeout_ms":100,"publish_timeout_ms":5000,"max_retries":3,"retry_delay_ms":1000}},"disable":{"summary":"Disable publishing","description":"Because the call is a full replace, the stored URL, exchange, queue and events are cleared and the transport is unregistered.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"RabbitMQ configuration saved and the publisher cache rebuilt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRabbitMQConfigSaveResponse"},"example":{"code":200,"data":{"Details":"RabbitMQ configuration saved successfully","Enabled":true},"success":true}}}},"400":{"description":"Bad Request: invalid JSON (including JSON objects in `queue_arguments`/`exchange_arguments`), an unknown event name, an invalid exchange/queue type, or a tuning value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON or a field has the wrong type","value":{"code":400,"error":"could not decode payload","success":false}},"unsupported_event_type":{"summary":"Unknown event name in events","value":{"code":400,"error":"unsupported event type: MessageReceived","success":false}},"invalid_exchange_type":{"summary":"exchange_type is not topic, direct, fanout or headers","value":{"code":400,"error":"invalid exchange_type: fan-out. Must be one of: topic, direct, fanout, headers","success":false}},"invalid_queue_type":{"summary":"queue_type is not classic, quorum or stream","value":{"code":400,"error":"invalid queue_type: lazy. Must be one of: classic, quorum, stream","success":false}},"positive_value_required":{"summary":"A tuning value that must be positive is 0 or negative","value":{"code":400,"error":"worker_count must be greater than 0","success":false}},"non_negative_value_required":{"summary":"A tuning value that must be non-negative is negative","value":{"code":400,"error":"max_retries must be non-negative","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the database update failed, or the cache/publisher could not be rebuilt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"save_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to save RabbitMQ configuration","success":false}},"cache_failed":{"summary":"Cache reload or publisher rebuild failed","value":{"code":500,"error":"failed to update RabbitMQ cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session RabbitMQ"],"summary":"Get the RabbitMQ configuration and queue statistics","description":"Returns the stored RabbitMQ publisher configuration of this instance together with the dynamic queues this process has declared.\n\n**Rules:**\n- The password inside `config.url` is replaced by `***`.\n- Tuning fields (`connection_pool_size`, `worker_count`, ...) are only present when a value is stored.\n- `dead_letter_*`, `queue_arguments` and `exchange_arguments` are only present when non-empty; `message_ttl`, `max_length` and `max_length_bytes` only when greater than 0.\n- `stats` is in-memory state of this process (reset on restart) and is `null` when the RabbitMQ manager is not running.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored configuration (URL password masked) and in-memory queue statistics.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRabbitMQConfigGetResponse"},"example":{"code":200,"data":{"config":{"enabled":true,"url":"amqps://zzg_user:***@rabbitmq.example.com:5671/whatsapp","exchange":"whatsapp.events","exchange_type":"topic","queue":"user_{user_id}_event_{event_type}","queue_type":"quorum","routing_key":"whatsapp.{user_id}.{event_type}","events":"Message,ReadReceipt,Connected","durable":true,"auto_delete":false,"exclusive":false,"no_wait":false,"delivery_mode":2,"worker_count":50,"batch_size":500,"dead_letter_exchange":"dlx.zigzapy","dead_letter_routing_key":"dlq.events","message_ttl":86400000,"queue_arguments":"{\"x-overflow\":\"reject-publish\"}"},"stats":{"userID":"4e4942c7dee1deef99ab8fd9f7350de5","dynamicQueues":true,"createdQueues":2,"queueNames":["user_4e4942c7dee1deef99ab8fd9f7350de5_event_Message","user_4e4942c7dee1deef99ab8fd9f7350de5_event_ReadReceipt"]}},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get RabbitMQ configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"delete":{"tags":["Session RabbitMQ"],"summary":"Delete the RabbitMQ configuration","description":"Disables RabbitMQ publishing for this instance, clears the stored broker settings and unregisters the individual RabbitMQ transport.\n\n**Rules:**\n- Stores `enabled=false`, empty URL, exchange, exchange type, queue, queue type, routing key and events, `durable=true`, `auto_delete`/`exclusive`/`no_wait=false`, `delivery_mode=2`, and NULL dead-letter, TTL, length and argument fields.\n- Publisher tuning fields (`connection_pool_size`, `worker_count`, `queue_buffer_size`, `batch_size`, timeouts and retries) are not reset.\n- Exchanges and queues already declared on the broker are not deleted.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"RabbitMQ configuration removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRabbitMQConfigDeleteResponse"},"example":{"code":200,"data":{"Details":"RabbitMQ configuration deleted successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the database update failed, or the cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"delete_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to delete RabbitMQ configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update RabbitMQ cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/rabbitmq/test":{"post":{"tags":["Session RabbitMQ"],"summary":"Test the RabbitMQ connection and publish a test message","description":"Verifies the stored RabbitMQ configuration end to end: it reloads the configuration, connects to the broker,\ndeclares the configured topology, starts the publisher and publishes one test event.\n\n**Rules:**\n- No request body: the test uses the configuration saved with `POST /session/rabbitmq/config`.\n- Fails with **400** when RabbitMQ is disabled for this instance.\n- The published test event has type `test` and a payload with `test: true`, a message, a Unix timestamp and the user ID; consumers bound to the routing key receive it.\n- A successful test leaves the publisher initialized for normal event delivery.\n- The broker URL is never echoed: `data.URL` is always `***`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Broker reachable, topology declared and test message published.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionRabbitMQTestResponse"},"example":{"code":200,"data":{"Details":"RabbitMQ connection test successful","Exchange":"whatsapp.events","ExchangeType":"topic","Queue":"user_{user_id}_event_{event_type}","QueueType":"quorum","RoutingKey":"whatsapp.{user_id}.{event_type}","TestMessage":"Test message published successfully","URL":"***"},"success":true}}}},"400":{"description":"Bad Request: RabbitMQ is not enabled for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"RabbitMQ is not enabled for this user","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration could not be read or reloaded, the broker connection or topology declaration failed, the publisher could not start, or the test message could not be published.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"read_failed":{"summary":"Configuration could not be read","value":{"code":500,"error":"failed to get RabbitMQ configuration","success":false}},"refresh_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to refresh RabbitMQ configuration: user config not found in cache for RabbitMQ refresh","success":false}},"not_cached":{"summary":"Reloaded configuration missing from the manager","value":{"code":500,"error":"failed to retrieve RabbitMQ configuration from cache","success":false}},"connection_failed":{"summary":"Broker unreachable or credentials rejected","value":{"code":500,"error":"RabbitMQ connection test failed: failed to connect to RabbitMQ: dial tcp 203.0.113.10:5672: connect: connection refused","success":false}},"init_failed":{"summary":"Publisher could not start after the test","value":{"code":500,"error":"failed to initialize RabbitMQ client after test: failed to open channel: channel/connection is not open","success":false}},"publish_failed":{"summary":"Test message not published","value":{"code":500,"error":"failed to publish test message: publish timeout","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/skipmedia/config":{"post":{"tags":["Session Skips"],"summary":"Turn media download for events on or off","description":"Controls whether this instance downloads the media (images, videos, audio, documents, stickers) of message events.\nWith the flag on, events are still delivered with the WhatsApp message metadata, but without base64 content and without S3 uploads.\n\n**Rules:**\n- `enabled: true` skips media download; `false` restores it. An omitted `enabled` is treated as `false`.\n- Media is skipped when **any** of these is on: the `-skipmedia` command-line flag, the `GLOBAL_SKIP_MEDIA_DOWNLOAD` environment variable, or this per-instance flag. This endpoint cannot override the first two.\n- Takes effect for the next events: the user configuration cache is reloaded immediately.\n\n**Use Cases:**\n- High-volume instances that only need text and message metadata\n- Reducing bandwidth and S3 storage when media is fetched on demand with `/chat/download*`\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkipMediaConfig"},"examples":{"skip_media":{"summary":"Skip media download","description":"Events keep message metadata but carry no base64 media and nothing is uploaded to S3.","value":{"enabled":true}},"download_media":{"summary":"Download media again","description":"Media is downloaded (and uploaded to S3 when configured) unless the flag or environment variable forces the skip.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Flag stored and cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipMediaUpdateResponse"},"example":{"code":200,"data":{"Details":"Skip media download configuration updated successfully","SkipMediaDownload":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be stored or the media cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update skip media download configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update skip media cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Skips"],"summary":"Get the media download skip setting","description":"Returns the per-instance media download flag together with the server-wide environment setting, so clients can tell why media is missing from events.\n\n**Rules:**\n- `UserSkipMediaDownload` is the value stored with `POST /session/skipmedia/config` (`false` when never set).\n- `GlobalSkipMediaDownload` mirrors `GLOBAL_SKIP_MEDIA_DOWNLOAD` and is read-only.\n- The `-skipmedia` command-line flag is not reported, but it also forces the skip when set.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Per-instance and server-wide media skip settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipMediaGetResponse"},"example":{"code":200,"data":{"UserSkipMediaDownload":true,"GlobalSkipMediaDownload":false,"Details":"Skip media download configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get skip media download configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/skipgroups/config":{"post":{"tags":["Session Skips"],"summary":"Ignore or process group chat events","description":"Controls whether this instance drops every event that comes from WhatsApp groups (`@g.us`), so only direct chats, newsletters and broadcasts reach webhooks and transports.\n\n**Rules:**\n- `enabled: true` drops group events; `false` processes them again. An omitted `enabled` is treated as `false`.\n- Dropped event types: `Message` and `Receipt` in group chats, `ChatPresence` in groups, `GroupInfo` and `JoinedGroup`.\n- Dropped events are discarded before any processing: no media download, no webhook, no RabbitMQ/SQS/Redis/WebSocket delivery.\n- The server-wide `GLOBAL_SKIP_GROUPS` environment variable drops group events for every instance, regardless of this flag.\n- Sending to groups through the API is not affected.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkipGroupsConfig"},"examples":{"ignore_groups":{"summary":"Ignore group events","description":"A support bot that only answers direct chats stops receiving group traffic.","value":{"enabled":true}},"process_groups":{"summary":"Process group events again","description":"Group messages, receipts and group updates are delivered again.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Flag stored and cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipGroupsUpdateResponse"},"example":{"code":200,"data":{"Details":"Skip groups configuration updated successfully","SkipGroups":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be stored or the groups cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update skip groups configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update skip groups cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Skips"],"summary":"Get the group events skip setting","description":"Returns whether this instance currently drops events from WhatsApp groups.\n\n**Rules:**\n- `SkipGroups` is the per-instance value (`false` when never set).\n- The server-wide `GLOBAL_SKIP_GROUPS` environment variable is not included in this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Per-instance group skip flag.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipGroupsGetResponse"},"example":{"code":200,"data":{"SkipGroups":true,"Details":"Skip groups configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get skip groups configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/skipnewsletters/config":{"post":{"tags":["Session Skips"],"summary":"Ignore or process newsletter (channel) events","description":"Controls whether this instance drops events that come from WhatsApp newsletters (Channels, `@newsletter`).\n\n**Rules:**\n- `enabled: true` drops newsletter events; `false` processes them again. An omitted `enabled` is treated as `false`.\n- Dropped event types: `Message` and `Receipt` in newsletter chats, `ChatPresence` in newsletters, `NewsletterJoin`, `NewsletterLeave`, `NewsletterMuteChange` and `NewsletterLiveUpdate`.\n- Dropped events never reach media download, webhooks or any transport.\n- The server-wide `GLOBAL_SKIP_NEWSLETTERS` environment variable drops newsletter events for every instance, regardless of this flag.\n- `/newsletter/*` endpoints keep working.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkipNewslettersConfig"},"examples":{"ignore_newsletters":{"summary":"Ignore channel events","description":"Followed channels can post many updates; this keeps them out of the webhook.","value":{"enabled":true}},"process_newsletters":{"summary":"Process channel events again","description":"Newsletter messages and follow/mute updates are delivered again.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Flag stored and cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipNewslettersUpdateResponse"},"example":{"code":200,"data":{"Details":"Skip newsletters configuration updated successfully","SkipNewsletters":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be stored or the newsletters cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update skip newsletters configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update skip newsletters cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Skips"],"summary":"Get the newsletter events skip setting","description":"Returns whether this instance currently drops events from WhatsApp newsletters (Channels).\n\n**Rules:**\n- `SkipNewsletters` is the per-instance value (`false` when never set).\n- The server-wide `GLOBAL_SKIP_NEWSLETTERS` environment variable is not included in this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Per-instance newsletter skip flag.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipNewslettersGetResponse"},"example":{"code":200,"data":{"SkipNewsletters":false,"Details":"Skip newsletters configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get skip newsletters configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/skipbroadcasts/config":{"post":{"tags":["Session Skips"],"summary":"Ignore or process broadcast and status events","description":"Controls whether this instance drops events from broadcast chats, which include contacts' Status updates (`status@broadcast`) and broadcast lists (`@broadcast`).\n\n**Rules:**\n- `enabled: true` drops broadcast events; `false` processes them again. An omitted `enabled` is treated as `false`.\n- Dropped event types: `Message` and `Receipt` whose chat JID contains `@broadcast`, and `ChatPresence` in those chats.\n- Dropped events never reach media download, webhooks or any transport. Skipping Status traffic also avoids downloading status media.\n- The server-wide `GLOBAL_SKIP_BROADCASTS` environment variable drops broadcast events for every instance, regardless of this flag.\n- Publishing your own status with `/status/send/*` is not affected.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkipBroadcastsConfig"},"examples":{"ignore_status":{"summary":"Ignore Status and broadcast events","description":"Contacts' Status posts and their receipts stop reaching the webhook.","value":{"enabled":true}},"process_status":{"summary":"Process Status and broadcast events again","description":"Status posts and broadcast list messages are delivered again.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Flag stored and cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipBroadcastsUpdateResponse"},"example":{"code":200,"data":{"Details":"Skip broadcasts configuration updated successfully","SkipBroadcasts":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be stored or the broadcasts cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update skip broadcasts configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update skip broadcasts cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Skips"],"summary":"Get the broadcast and status events skip setting","description":"Returns whether this instance currently drops events from broadcast chats and contacts' Status updates.\n\n**Rules:**\n- `SkipBroadcasts` is the per-instance value (`false` when never set).\n- The server-wide `GLOBAL_SKIP_BROADCASTS` environment variable is not included in this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Per-instance broadcast skip flag.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipBroadcastsGetResponse"},"example":{"code":200,"data":{"SkipBroadcasts":true,"Details":"Skip broadcasts configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get skip broadcasts configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/skipownmessages/config":{"post":{"tags":["Session Skips"],"summary":"Ignore or process events about your own messages","description":"Controls whether this instance drops events generated by messages sent from this WhatsApp account (from the phone, other linked devices or this API).\n\n**Rules:**\n- `enabled: true` drops own-message events; `false` processes them again. An omitted `enabled` is treated as `false`.\n- Dropped event types: `Message` and `Receipt` with `IsFromMe`, and `DeleteForMe`, `Star` and `MediaRetry` events about messages sent by this account.\n- Dropped events never reach media download, webhooks or any transport.\n- The server-wide `GLOBAL_SKIP_OWN_MESSAGES` environment variable drops own `Message`, `Receipt` and `MediaRetry` events for every instance, regardless of this flag.\n- Sending through the API still works and still returns the message ID in the HTTP response.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkipOwnMessagesConfig"},"examples":{"ignore_own":{"summary":"Ignore own messages","description":"A chatbot that must never react to its own replies stops receiving them as events.","value":{"enabled":true}},"process_own":{"summary":"Process own messages again","description":"Messages typed on the phone or sent by other devices are delivered again, useful for inbox mirroring.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Flag stored and cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipOwnMessagesUpdateResponse"},"example":{"code":200,"data":{"Details":"Skip own messages configuration updated successfully","SkipOwnMessages":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be stored or the own-messages cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update skip own messages configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update skip own messages cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Skips"],"summary":"Get the own-message events skip setting","description":"Returns whether this instance currently drops events about messages sent by this WhatsApp account.\n\n**Rules:**\n- `SkipOwnMessages` is the per-instance value (`false` when never set).\n- The server-wide `GLOBAL_SKIP_OWN_MESSAGES` environment variable is not included in this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Per-instance own-message skip flag.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipOwnMessagesGetResponse"},"example":{"code":200,"data":{"SkipOwnMessages":false,"Details":"Skip own messages configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flag could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get skip own messages configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/skipcalls/config":{"post":{"tags":["Session Skips"],"summary":"Auto-reject incoming calls","description":"Turns automatic rejection of incoming WhatsApp calls on or off for this instance and sets the text message sent to the caller after rejecting.\n\n**Rules:**\n- `enabled: true` rejects every incoming 1:1 call offer and group call notice, then sends `reject_message` to the caller as a text message. An omitted `enabled` is treated as `false`.\n- `CallOffer` and `CallOfferNotice` events are dropped (not delivered to webhooks or transports) while the flag is on.\n- `reject_message` empty or omitted is stored as `Sorry, I cannot take calls at the moment.`\n- `reject_type` accepts `busy`, `declined` or `unavailable`; empty or omitted is stored as `busy`; anything else returns **400**. The value is stored and logged only: the rejection sent to WhatsApp is the same for every type.\n- When the native calls engine owns inbound calls for the instance (`/call/config`), the engine handles the call and no automatic rejection or message is sent.\n- The server-wide `GLOBAL_SKIP_CALLS` environment variable also rejects calls and drops `CallOffer` events for every instance, regardless of this flag.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkipCallsConfig"},"examples":{"reject_with_message":{"summary":"Reject calls and reply with a custom text","description":"Every incoming call is rejected and the caller receives the message as a WhatsApp text.","value":{"enabled":true,"reject_message":"Sorry, I cannot take calls right now. Please send a message.","reject_type":"busy"}},"reject_with_defaults":{"summary":"Reject calls with the default text","description":"Omitting `reject_message` and `reject_type` stores the default message and `busy`.","value":{"enabled":true}},"accept_calls":{"summary":"Stop rejecting calls","description":"Calls ring normally again and call events are delivered. The stored message and type are overwritten with the defaults.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Settings stored and cache reloaded. `data` echoes the stored values, including defaults.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipCallsUpdateResponse"},"example":{"code":200,"data":{"Details":"Skip calls configuration updated successfully","SkipCalls":true,"RejectMessage":"Sorry, I cannot take calls right now. Please send a message.","RejectType":"busy"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `reject_type` is not an accepted value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"invalid_reject_type":{"summary":"reject_type is not busy, declined or unavailable","value":{"code":400,"error":"invalid reject_type, must be: busy, declined, or unavailable","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the settings could not be stored or the calls cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update skip calls configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update skip calls cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Skips"],"summary":"Get the call auto-reject settings","description":"Returns whether incoming calls are automatically rejected for this instance and which message is sent to the caller.\n\n**Rules:**\n- Defaults are returned when nothing is stored: `SkipCalls=false`, `RejectMessage=Sorry, I cannot take calls at the moment.`, `RejectType=busy`.\n- The server-wide `GLOBAL_SKIP_CALLS` environment variable is not included in this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored auto-reject settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionSkipCallsGetResponse"},"example":{"code":200,"data":{"SkipCalls":true,"RejectMessage":"Sorry, I cannot take calls right now. Please send a message.","RejectType":"busy","Details":"Skip calls configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the settings could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get skip calls configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/globaltransports/config":{"post":{"tags":["Session Global Transports"],"summary":"Opt this instance out of global event transports","operationId":"configureGlobalTransportSkips","description":"Sets per-instance flags that make the server-wide (global) event dispatcher skip this instance for selected transports:\nthe global webhook, RabbitMQ, SQS, Redis, WebSocket and the shared S3 media enrichment.\n\n**Rules:**\n- **Partial update:** only the flags present in the body are written; omitted flags keep their stored value.\n- At least one flag is required; `{}` or a body with only unknown fields returns **400** `no fields provided`.\n- Unknown fields are ignored. A non-boolean flag value or invalid JSON returns **400** `invalid request body`.\n- Only the global dispatcher is affected. The instance's own webhook (`/webhook`) and RabbitMQ (`/session/rabbitmq/config`) keep working.\n- The response is built from the reloaded cache. If the cache reload fails after the database update, the request still returns **200** and the flags apply once the cache is refreshed.\n\n**Use Cases:**\n- Keep one tenant's traffic out of a shared global RabbitMQ or SQS queue\n- Stop uploading one instance's media to the global S3 bucket\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalTransportSkipsRequest"},"examples":{"skip_rabbitmq_and_s3":{"summary":"Opt out of global RabbitMQ and S3","description":"Only these two flags change; webhook, SQS, Redis and WebSocket keep their stored values.","value":{"skipGlobalRabbitMQ":true,"skipGlobalS3":true}},"restore_webhook":{"summary":"Receive the global webhook again","description":"Clears a single flag without touching the others.","value":{"skipGlobalWebhook":false}},"set_all_flags":{"summary":"Set every flag explicitly","description":"Useful to replicate a known configuration across instances.","value":{"skipGlobalWebhook":false,"skipGlobalRabbitMQ":true,"skipGlobalSQS":false,"skipGlobalRedis":false,"skipGlobalWebSocket":false,"skipGlobalS3":true}}}}}},"responses":{"200":{"description":"Flags stored. `data` contains all six flags after the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalTransportSkipsResponse"},"example":{"code":200,"data":{"skipGlobalWebhook":false,"skipGlobalRabbitMQ":true,"skipGlobalSQS":false,"skipGlobalRedis":false,"skipGlobalWebSocket":false,"skipGlobalS3":true,"details":"Global transport skip configuration updated successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, a flag is not a boolean, or no known flag was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_request_body":{"summary":"Invalid JSON or non-boolean flag","value":{"code":400,"error":"invalid request body","success":false}},"no_fields_provided":{"summary":"No known flag in the body","value":{"code":400,"error":"no fields provided","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the flags could not be stored.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to update transport configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Global Transports"],"summary":"Get the global transport opt-out flags","operationId":"getGlobalTransportSkips","description":"Returns the six per-instance flags that the global event dispatcher checks before delivering this instance's events to each global transport.\n\n**Rules:**\n- Values come from the user configuration cache; on a cache miss the configuration is loaded from the database first.\n- A flag that was never set is returned as `false` (the instance receives that global transport).\n- Whether each global transport is enabled at all is a server setting and is not part of this response.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Current opt-out flags of this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GlobalTransportSkipsResponse"},"example":{"code":200,"data":{"skipGlobalWebhook":false,"skipGlobalRabbitMQ":true,"skipGlobalSQS":false,"skipGlobalRedis":false,"skipGlobalWebSocket":false,"skipGlobalS3":true,"details":"Global transport skip configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration was not cached and could not be loaded from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to load user configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/session/presence/config":{"post":{"tags":["Session Presence"],"summary":"Turn automatic \"unavailable\" presence on or off","operationId":"configureAutoPresenceUnavailable","description":"Controls whether this instance marks itself as unavailable right after connecting, so the phone keeps receiving push notifications while the API session stays online.\n\n**Rules:**\n- `enabled: true`: after every connection (and after the initial app-state sync) the gateway sends the protocol-required `available` presence, waits 3 seconds, then sends `unavailable`.\n- `enabled: false` (default, also used when `enabled` is omitted): the instance stays `available` after connecting, which can silence notifications on the phone.\n- The setting applies from the next connection or app-state sync; it does not change the current presence immediately.\n- Manual presence changes with `POST /user/presence` are not affected.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPresenceConfigRequest"},"examples":{"keep_phone_notifications":{"summary":"Go unavailable 3 seconds after connecting","description":"Recommended when the same account is also used on the phone and notifications must keep arriving.","value":{"enabled":true}},"stay_available":{"summary":"Stay available after connecting","description":"Restores the default behavior.","value":{"enabled":false}}}}}},"responses":{"200":{"description":"Setting stored and presence cache reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPresenceConfigUpdateResponse"},"example":{"code":200,"data":{"Details":"Auto presence unavailable configuration updated successfully","AutoPresenceUnavailable":true},"success":true}}}},"400":{"description":"Bad Request: the body is empty or not valid JSON, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the setting could not be stored or the presence cache could not be reloaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_failed":{"summary":"Database update failed","value":{"code":500,"error":"failed to update auto presence unavailable configuration","success":false}},"cache_failed":{"summary":"Cache reload failed","value":{"code":500,"error":"failed to update presence cache","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"get":{"tags":["Session Presence"],"summary":"Get the automatic \"unavailable\" presence setting","operationId":"getAutoPresenceUnavailableConfig","description":"Returns whether this instance sends an `unavailable` presence 3 seconds after connecting.\n\n**Rules:**\n- `AutoPresenceUnavailable` is `false` when the setting was never stored.\n- This reports the stored setting, not the presence currently shown to contacts.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored setting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionPresenceConfigGetResponse"},"example":{"code":200,"data":{"AutoPresenceUnavailable":true,"Details":"Auto presence unavailable configuration retrieved successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the setting could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"failed to get auto presence unavailable configuration","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/info":{"post":{"tags":["User"],"summary":"Get user information","description":"Fetches WhatsApp profile data for one or more accounts: status (about) text, profile picture ID, business verification, LID and the list of devices currently registered to each account.\n\n**Rules:**\n- Send the numbers in `phone`, or in the legacy `Phone` field. Both accept a single string or an array of strings; `phone` is read first and `Phone` only when `phone` yields no value.\n- Each value may be a phone number with country code (a leading `+` is stripped) or a user JID. The first unparseable value aborts the request with **400**.\n- Non-string items inside an array are ignored.\n- A missing WhatsApp session returns **500** `no session`; a failed WhatsApp query returns **500**.\n\n**Response:**\n- `data.users` is an object keyed by JID. `verified_name`, `business_name`, `lid` and `first_device` are omitted when empty.\n- `verified_certificate` only appears for business accounts that carry a certificate.\n- `devices[].device` is the platform name derived from the device ID (see `POST /device/platform`).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfoRequest"},"examples":{"single":{"summary":"One phone number","description":"A single number sent as a plain string.","value":{"phone":"5511999999999"}},"several":{"summary":"Several phone numbers","description":"Up to the WhatsApp usync limits; every value must be a valid number or JID.","value":{"phone":["5511999999999","5511988888888"]}},"legacy_field":{"summary":"Legacy Phone field with a JID","description":"The capitalized `Phone` field is still accepted for backward compatibility.","value":{"Phone":["5511999999999@s.whatsapp.net"]}}}}}},"responses":{"200":{"description":"Profile data keyed by JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserInfoResponse"},"examples":{"personal_account":{"summary":"Personal account with two devices","value":{"code":200,"data":{"users":{"5511999999999@s.whatsapp.net":{"jid":"5511999999999@s.whatsapp.net","status":"Available","picture_id":"1700000000","lid":"123456789012345@lid","is_business_account":false,"device_count":2,"first_device":"5511999999999@s.whatsapp.net","devices":[{"user":"5511999999999","agent":"0","device":"UNKNOWN","server":"s.whatsapp.net","ad":"5511999999999.0:0@s.whatsapp.net","jid":"5511999999999@s.whatsapp.net"},{"user":"5511999999999","agent":"0","device":"SAFARI","server":"s.whatsapp.net","ad":"5511999999999.0:5@s.whatsapp.net","jid":"5511999999999:5@s.whatsapp.net"}]}}},"success":true}},"business_account":{"summary":"Verified business account","value":{"code":200,"data":{"users":{"5511988888888@s.whatsapp.net":{"jid":"5511988888888@s.whatsapp.net","status":"Open Monday to Friday","picture_id":"1728656243","verified_name":"Example Store","business_name":"Example Store","is_business_account":true,"device_count":1,"first_device":"5511988888888@s.whatsapp.net","verified_certificate":{"has_signature":true,"has_server_signature":true},"devices":[{"user":"5511988888888","agent":"0","device":"UNKNOWN","server":"s.whatsapp.net","ad":"5511988888888.0:0@s.whatsapp.net","jid":"5511988888888@s.whatsapp.net"}]}}},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, no phone value, a field with the wrong type, or an unparseable number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload: unexpected EOF","success":false}},"phone_wrong_type":{"summary":"phone is neither a string nor an array","value":{"code":400,"error":"phone field must be string or array of strings","success":false}},"legacy_phone_wrong_type":{"summary":"Phone is neither a string nor an array","value":{"code":400,"error":"Phone field must be string or array of strings","success":false}},"missing_phone":{"summary":"Neither phone nor Phone provided","value":{"code":400,"error":"missing phone numbers in payload. Use 'Phone' or 'phone' field","success":false}},"invalid_phone":{"summary":"A value is not a valid number or JID","value":{"code":400,"error":"invalid phone number: @s.whatsapp.net","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the WhatsApp user-info query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"Failed to get user info: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/privacy/settings":{"get":{"tags":["User"],"summary":"Get privacy settings fresh from WhatsApp","description":"Fetches the privacy settings of the connected account directly from WhatsApp, bypassing the library cache, and returns them as flat fields.\n\n**Rules:**\n- No query parameters or body. The cache is bypassed on every call.\n- Unlike `GET /privacy/settings`, a failed fetch is reported as **500** instead of returning empty values.\n\n**Values:**\n- `group_add`, `last_seen`, `status`, `profile`: `all`, `contacts`, `contact_blacklist` or `none`.\n- `read_receipts`: `all` or `none`. `online`: `all` or `match_last_seen`. `call_add`: `all` or `known`.\n- A field is an empty string when WhatsApp did not report it.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Current privacy settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPrivacySettingsResponse"},"example":{"code":200,"data":{"group_add":"contacts","last_seen":"contacts","status":"contacts","profile":"all","read_receipts":"all","online":"match_last_seen","call_add":"all"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the privacy query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"fetch_failed":{"summary":"WhatsApp privacy query failed","value":{"code":500,"error":"failed to get privacy settings: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/pushname":{"post":{"tags":["User"],"summary":"Change your push name","description":"Changes the push name (display name) of the connected account, the name recipients see next to your number when you are not in their contacts.\n\n**Rules:**\n- `push_name` is required and cannot be empty.\n- The change is sent as an app-state `setting_pushName` mutation. On sync conflicts (409 or LTHash mismatch) the gateway runs a full app-state sync and retries up to 3 times before failing.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePushNameRequest"},"examples":{"company_name":{"summary":"Company display name","description":"A short brand name shown to people who have not saved your number.","value":{"push_name":"Example Store"}},"agent_name":{"summary":"Personal display name","description":"Any non-empty text is accepted; emoji are allowed.","value":{"push_name":"Maria from Support"}}}}}},"responses":{"200":{"description":"Push name updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPushNameResponse"},"example":{"code":200,"data":{"success":true,"message":"Push name updated successfully","push_name":"Example Store"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON or empty `push_name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"empty_push_name":{"summary":"push_name missing or empty","value":{"code":400,"error":"push name cannot be empty","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the app-state update failed after the recovery attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"App-state update failed","value":{"code":500,"error":"failed to change push name: app state error (not recoverable): websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/contact/info":{"post":{"tags":["User"],"summary":"Get combined contact information","description":"Builds one consolidated view of a contact from several WhatsApp sources: registration check, user info (status, devices), profile picture (downloaded and embedded as base64), saved contact names, LID mapping and business profile.\n\n**Rules:**\n- `phone` is required: a phone number, a user JID or a LID (`@lid`).\n- A LID is first translated to the phone number using the local LID store; when no mapping is cached the request returns **404**.\n- If the number is not on WhatsApp, the call still returns **200** with `is_on_whatsapp: false` and the lookup sections set to `null`.\n- The registration check is mandatory (**500** when it fails); user info, avatar, contact names and business profile failures only null their section.\n- The avatar lookup has a 10-second timeout and is skipped when WhatsApp reports no picture.\n\n**Response:**\n- `input_type` tells how `phone` was interpreted: `phone`, `jid` or `lid`.\n- `jid` and `phone` are always phone-shaped; `lid` is the contact LID when known.\n- `avatar.base64` is present only when the gateway could download the picture; `preview_url` only when both sizes were fetched.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactInfoRequest"},"examples":{"phone_number":{"summary":"Phone number","description":"Phone number with country code, without `+`.","value":{"phone":"5511999999999"}},"jid_format":{"summary":"User JID","description":"A full phone JID; `input_type` becomes `jid`.","value":{"phone":"5511999999999@s.whatsapp.net"}},"lid_format":{"summary":"LID","description":"Requires a cached LID-to-phone mapping; `input_type` becomes `lid`.","value":{"phone":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"Consolidated contact information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactInfoResponse"},"examples":{"business_contact":{"summary":"Registered business contact","value":{"code":200,"data":{"phone":"5511988888888","jid":"5511988888888@s.whatsapp.net","input_type":"phone","lid":"123456789012346@lid","is_on_whatsapp":true,"verified_name":"Example Store","user_info":{"status":"Open Monday to Friday","picture_id":"1728656243","verified_name":"Example Store","is_business_account":true,"device_count":1},"devices":[{"user":"5511988888888","agent":"0","device":"UNKNOWN","server":"s.whatsapp.net","ad":"5511988888888.0:0@s.whatsapp.net","jid":"5511988888888@s.whatsapp.net"}],"avatar":{"url":"https://pps.whatsapp.net/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2","id":"1728656243","type":"image","direct_path":"/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2","base64":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2Q==","width":640,"height":640,"preview_url":"https://pps.whatsapp.net/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?stp=dst-jpg_s96x96&ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2","preview_direct_path":"/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?stp=dst-jpg_s96x96&ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"},"contact_names":{"first_name":"Example","full_name":"Example Store","push_name":"Example Store","business_name":"Example Store"},"business_profile":{"address":"100 Example Avenue, Sao Paulo","email":"contact@example.com","business_hours_timezone":"America/Sao_Paulo","categories":[{"id":"133436743388217","name":"Shopping & Retail"}],"profile_options":{"commerce_experience":"catalog"},"business_hours":[{"day_of_week":"mon","mode":"specific_hours","open_time":"09:00","close_time":"18:00"}]}},"success":true}},"not_on_whatsapp":{"summary":"Number without WhatsApp","value":{"code":200,"data":{"phone":"5511977777777","jid":"5511977777777@s.whatsapp.net","input_type":"phone","is_on_whatsapp":false,"lid":null,"user_info":null,"devices":null,"avatar":null,"contact_names":null,"business_profile":null},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, `phone` missing, or `phone` is not a valid number/JID/LID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone":{"summary":"phone missing","value":{"code":400,"error":"missing phone in payload","success":false}},"invalid_phone":{"summary":"phone cannot be parsed","value":{"code":400,"error":"invalid phone number, JID, or LID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: the LID has no cached phone mapping on this gateway.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"could not resolve LID to phone number. The LID mapping may not be cached locally","success":false}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, LID store unavailable, or the registration check failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"lid_store_unavailable":{"summary":"LID input but the LID store is not initialized","value":{"code":500,"error":"LID store not available","success":false}},"check_failed":{"summary":"Registration check failed","value":{"code":500,"error":"failed to check WhatsApp registration: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/contact/add":{"post":{"tags":["User"],"summary":"Add or rename a contact","description":"Saves a contact name in the account address book, or renames an existing contact. The change is synced to the phone and every linked device through app state.\n\n**Rules:**\n- `phone` and `full_name` are required and cannot be empty.\n- `phone` accepts a phone number with country code or a user JID.\n- On sync conflicts (409 or LTHash mismatch) the gateway runs a full app-state sync and retries up to 3 times before failing with **500**.\n\n**Use Cases:**\n- Keep WhatsApp contact names aligned with a CRM\n- Save a lead so their profile photo and status become visible under \"My contacts\" privacy\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactAddRequest"},"examples":{"new_contact":{"summary":"Save a new contact","description":"Adds the number to the address book with the given name.","value":{"phone":"5511999999999","full_name":"Maria Silva"}},"rename_by_jid":{"summary":"Rename an existing contact by JID","description":"Sending an already saved contact replaces its name.","value":{"phone":"5511988888888@s.whatsapp.net","full_name":"Example Store - Sales"}}}}}},"responses":{"200":{"description":"Contact saved and synced.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactAddResponse"},"example":{"code":200,"data":{"success":true,"message":"Contact added successfully","phone":"5511999999999","full_name":"Maria Silva"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, a required field is empty, or `phone` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"empty_phone":{"summary":"phone missing or empty","value":{"code":400,"error":"phone number cannot be empty","success":false}},"empty_full_name":{"summary":"full_name missing or empty","value":{"code":400,"error":"full name cannot be empty","success":false}},"invalid_phone":{"summary":"phone cannot be parsed","value":{"code":400,"error":"could not parse phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the app-state update failed after the recovery attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"App-state update failed","value":{"code":500,"error":"failed to add contact: app state error (not recoverable): websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/contact/remove":{"post":{"tags":["User"],"summary":"Remove a saved contact","description":"Deletes a contact from the account address book. The removal is synced to the phone and every linked device; chats and messages are kept.\n\n**Rules:**\n- `phone` is required: a phone number with country code or a user JID.\n- Removing a number that is not saved is forwarded to WhatsApp as is.\n- On sync conflicts (409 or LTHash mismatch) the gateway runs a full app-state sync and retries up to 3 times before failing with **500**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactRemoveRequest"},"examples":{"by_phone":{"summary":"Remove by phone number","description":"Phone number with country code, without `+`.","value":{"phone":"5511999999999"}},"by_jid":{"summary":"Remove by JID","description":"A full phone JID is accepted as well.","value":{"phone":"5511999999999@s.whatsapp.net"}}}}}},"responses":{"200":{"description":"Contact removed and synced.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactRemoveResponse"},"example":{"code":200,"data":{"success":true,"message":"Contact removed successfully","phone":"5511999999999"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `phone` empty, or `phone` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"empty_phone":{"summary":"phone missing or empty","value":{"code":400,"error":"phone number cannot be empty","success":false}},"invalid_phone":{"summary":"phone cannot be parsed","value":{"code":400,"error":"could not parse phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the app-state update failed after the recovery attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"App-state update failed","value":{"code":500,"error":"failed to remove contact: app state error (not recoverable): websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/status":{"get":{"tags":["User"],"summary":"Get your status (about) text","description":"Returns the status (\"about\") text of the connected account, as WhatsApp currently reports it.\n\n**Rules:**\n- No query parameters or body. The session must be paired; before pairing the call returns **500** `could not get own JID`.\n- `status` is an empty string when no text is set.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Current status text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStatusGetResponse"},"example":{"code":200,"data":{"status":"Available for support 9am-6pm"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, session not paired, or the WhatsApp query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_paired":{"summary":"Session has no own JID yet","value":{"code":500,"error":"could not get own JID","success":false}},"query_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"failed to get status: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"post":{"tags":["User"],"summary":"Set your status (about) text","description":"Sets the status (\"about\") text of the connected account, shown on your profile to people allowed by your status privacy.\n\n**Rules:**\n- `status` is sent as given; an empty string or a missing field clears the text.\n- The gateway does not check the length; WhatsApp limits the text to 139 characters and rejects longer values with **500**.\n- Emoji and other multibyte text are sent as given (validated live with `💻 Conversa Labs`).\n- The text travels in the classic `<iq type=\"set\" xmlns=\"status\">` stanza, the same one the official web client uses for\n  the About field. The newer GraphQL \"text status\" mutation (emoji plus ephemeral duration) is gated per account and\n  answers `400 Bad Request` outside the rollout, so it is never used for a plain text status.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetMyStatusRequest"},"examples":{"business_hours":{"summary":"Set a status text","description":"Replaces the current about text.","value":{"status":"Available for support 9am-6pm"}},"clear":{"summary":"Clear the status text","description":"An empty string removes the about text.","value":{"status":""}}}}}},"responses":{"200":{"description":"Status text updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserStatusSetResponse"},"example":{"code":200,"data":{"success":true,"message":"Status updated successfully","status":"Available for support 9am-6pm"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp rejected the status text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"set_failed":{"summary":"WhatsApp rejected the update","value":{"code":500,"error":"failed to set status: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/update":{"post":{"tags":["User"],"summary":"Update your gateway user name or token","description":"Changes the gateway user record of the caller: its display name, its API token, or both. This does not touch the WhatsApp profile (see `POST /user/pushname` for that).\n\n**Rules:**\n- Send `name`, `token` or both. Empty strings and values equal to the current ones are ignored; if nothing changes the request returns **400**.\n- `name` may have at most 255 characters. A new `token` needs at least 8 characters and must not belong to another user (**409**).\n- The update uses optimistic locking on the current token; a concurrent change returns **409**.\n\n**Side effects:**\n- When the token changes, the old token stops authenticating immediately and the cached user configuration is reloaded under the new token.\n- The response echoes the final token in clear text; treat it as a secret.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateRequest"},"examples":{"rename":{"summary":"Change only the name","description":"The token stays the same.","value":{"name":"sales-team"}},"rotate_token":{"summary":"Rotate the API token","description":"The old token is revoked as soon as the response is sent.","value":{"token":"9f8e7d6c5b4a3210fedcba98"}},"both":{"summary":"Change name and token","description":"Both values are written in the same update.","value":{"name":"support-team","token":"0a1b2c3d4e5f67890a1b2c3d"}}}}}},"responses":{"200":{"description":"User record updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdateResponse"},"example":{"code":200,"data":{"id":"3f0b9f2c8e7d4a6b9c1d2e3f4a5b6c7d","name":"sales-team","token":"9f8e7d6c5b4a3210fedcba98","message":"Profile updated successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, no effective change, name too long, or token shorter than 8 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"error":"Invalid JSON","success":false}},"no_changes":{"summary":"Both fields empty or equal to the current values","value":{"code":400,"error":"No changes detected","success":false}},"name_too_long":{"summary":"name longer than 255 characters","value":{"code":400,"error":"Name too long (max 255 characters)","success":false}},"token_too_short":{"summary":"New token shorter than 8 characters","value":{"code":400,"error":"Token too short (min 8 characters)","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the new token belongs to another user, or the record changed during the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"token_in_use":{"summary":"Token already used by another user","value":{"code":409,"error":"Token already in use","success":false}},"concurrent_update":{"summary":"Record modified by another request","value":{"code":409,"error":"Profile was modified by another request. Please try again","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: database failure while checking or writing the record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"Failed to update profile: pq: could not serialize access due to concurrent update","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/business/profile":{"post":{"tags":["User"],"summary":"Get a business profile","description":"Returns the public WhatsApp Business profile of an account: address, email, categories, business hours and profile options, together with its status text and verified name.\n\n**Rules:**\n- `phone` is required: a phone number with country code or a user JID.\n- A personal account (no verified name) whose profile lookup fails with \"not found\" returns **404**; other lookup failures return **500**.\n- A verified business whose profile data cannot be read still returns **200** with `is_business_account: true` and `profile_data_available: false`.\n\n**Response:**\n- `open_time`/`close_time` are formatted as `HH:MM`; `categories`, `business_hours` and `profile_options` are `null` when the profile has none.\n- `verified_name`, `status` and `picture_id` are omitted when empty; `business_name` is never filled by this endpoint.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessProfileRequest"},"examples":{"by_phone":{"summary":"Business phone number","description":"Phone number with country code, without `+`.","value":{"phone":"5511988888888"}},"by_jid":{"summary":"Business JID","description":"A full phone JID is accepted as well.","value":{"phone":"5511988888888@s.whatsapp.net"}}}}}},"responses":{"200":{"description":"Business profile data.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserBusinessProfileResponse"},"examples":{"full_profile":{"summary":"Business with public profile data","value":{"code":200,"data":{"jid":"5511988888888@s.whatsapp.net","email":"contact@example.com","address":"100 Example Avenue, Sao Paulo","categories":[{"id":"133436743388217","name":"Shopping & Retail"}],"profile_options":{"commerce_experience":"catalog"},"business_hours_timezone":"America/Sao_Paulo","business_hours":[{"day_of_week":"mon","mode":"specific_hours","open_time":"09:00","close_time":"18:00"},{"day_of_week":"sat","mode":"open_24h","open_time":"","close_time":""}],"verified_name":"Example Store","status":"Open Monday to Friday","picture_id":"1728656243","is_business_account":true,"profile_data_available":true},"success":true}},"verified_without_profile":{"summary":"Verified business without readable profile data","value":{"code":200,"data":{"jid":"5511988888888@s.whatsapp.net","email":"","address":"","categories":null,"profile_options":null,"business_hours_timezone":"","business_hours":null,"verified_name":"Example Store","is_business_account":true,"profile_data_available":false},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, `phone` missing, or `phone` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone":{"summary":"phone missing","value":{"code":400,"error":"missing phone number in payload","success":false}},"invalid_phone":{"summary":"phone cannot be parsed","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: the account is not a WhatsApp Business account or has no public business profile.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"this number is not a WhatsApp Business account or does not have a public business profile","success":false}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the business profile query failed for another reason.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"failed to get business profile: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/check":{"post":{"tags":["User"],"summary":"Check if phone numbers are on WhatsApp","description":"Checks whether phone numbers have a WhatsApp account and returns, for each one, the phone JID, the LID, business verification data, the username and the default disappearing-message setting.\n\n**Rules:**\n- `Phone` is required and must be a non-empty array of strings (a plain string fails to decode and returns **400**). The field name is matched case-insensitively, so `phone` also works.\n- Send numbers in international format; the gateway passes them to WhatsApp as given.\n- A missing WhatsApp session returns **500** `no session`; a failed WhatsApp query returns **500**.\n\n**Response:**\n- `data.Users` has one entry per number, in the order returned by WhatsApp.\n- `JID` stays phone-shaped (`@s.whatsapp.net`) for backward compatibility; the LID is reported separately in `LID`.\n- `Username`, `VerifiedLevel` and `DisappearingMode` are omitted when WhatsApp does not report them. Usernames are still rolling out, so `Username` is usually absent.\n\n**Use Cases:**\n- Clean a contact list before a campaign\n- Discover the LID of a number before addressing it by LID\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Checkuser"},"examples":{"single":{"summary":"One number","description":"Checks a single number; the array form is mandatory even for one value.","value":{"Phone":["5511999999999"]}},"several":{"summary":"Several numbers","description":"Checks three numbers in one WhatsApp query.","value":{"Phone":["5511999999999","5511988888888","5511977777777"]}}}}}},"responses":{"200":{"description":"One result per queried number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCheckResponse"},"example":{"code":200,"data":{"Users":[{"Query":"5511988888888","IsInWhatsapp":true,"JID":"5511988888888@s.whatsapp.net","LID":"123456789012346@lid","VerifiedName":"Example Store","Username":"examplestore","VerifiedLevel":"high","DisappearingMode":{"enabled":true,"duration_sec":604800,"set_at":"2026-07-01T12:34:56Z"}},{"Query":"5511977777777","IsInWhatsapp":false,"JID":"5511977777777@s.whatsapp.net","LID":"","VerifiedName":""}]},"success":true}}}},"400":{"description":"Bad Request: the body cannot be decoded (for example `Phone` sent as a string) or the list is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Invalid JSON or Phone is not an array","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone":{"summary":"Phone missing or empty","value":{"code":400,"error":"missing Phone in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the WhatsApp registration query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"failed to check if users are on WhatsApp: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/presence":{"post":{"tags":["User"],"summary":"Set your global presence","description":"Sets the global presence of the connected account to `available` (online) or `unavailable` (offline). Contacts allowed by your \"online\" privacy setting see the change.\n\n**Rules:**\n- `type` is required and must be exactly `available` or `unavailable` (lower case).\n- WhatsApp requires the account push name to be known; right after pairing, before the push name syncs, sending presence fails with **500**.\n- Staying `available` keeps delivery receipts active and can stop push notifications on the phone. See `POST /session/presence/config` to switch back to `unavailable` automatically after connecting.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPresence"},"examples":{"available":{"summary":"Appear online","description":"Marks the account as online until changed or disconnected.","value":{"type":"available"}},"unavailable":{"summary":"Appear offline","description":"Marks the account as offline; the phone keeps receiving push notifications.","value":{"type":"unavailable"}}}}}},"responses":{"200":{"description":"Presence sent to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPresenceResponse"},"example":{"code":200,"data":{"Details":"Presence set successfuly"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, or `type` is not `available`/`unavailable`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"invalid_type":{"summary":"type missing or not allowed","value":{"code":400,"error":"invalid presence type. Allowed values: 'available', 'unavailable'","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp did not accept the presence (for example push name not synced yet).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"no_push_name":{"summary":"Device has no push name yet","description":"A freshly paired device has no push name until it is synced from the phone or set with `POST /user/pushname`; WhatsApp refuses presence without one.","value":{"code":500,"error":"failure sending presence to Whatsapp servers: push name not set on this device yet; set it with POST /user/pushname","success":false}},"send_failed":{"summary":"Presence not accepted","value":{"code":500,"error":"failure sending presence to Whatsapp servers","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/avatar":{"post":{"tags":["User"],"summary":"Get profile picture information","description":"Returns the profile picture URL and metadata of a contact, group or community, either the full image or the small preview thumbnail. The image itself is not downloaded by the gateway.\n\n**Features:**\n- `Preview: true` returns the thumbnail; `false` returns the full-resolution image.\n- `CommonGID` fetches a member's picture through a group you share, which can succeed when the contact restricts the picture to contacts.\n- `InviteCode` fetches a group picture before joining, using the invite code.\n- `PersonaID` fetches the picture of a Meta AI persona; `IsCommunity` marks a community JID.\n\n**Rules:**\n- `Phone` is required: phone number, user JID, group JID or community JID. Field names are matched case-insensitively.\n- `CommonGID`, when present, must be a valid JID (**400** otherwise).\n- A contact or group **without a profile photo** returns **500** `no avatar found` (some WhatsApp answers surface instead as `failed to get avatar: that user or group does not have a profile picture`).\n- Other WhatsApp errors, such as \"hidden by privacy\", return **500** with the reason in the message.\n- The returned `url` expires; download it promptly.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Checkavatar"},"examples":{"preview":{"summary":"Thumbnail of a contact","description":"Smallest payload; good for chat lists.","value":{"Phone":"5511999999999","Preview":true}},"full_via_group":{"summary":"Full picture through a shared group","description":"Uses a group both accounts belong to as the access context.","value":{"Phone":"5511999999999@s.whatsapp.net","Preview":false,"CommonGID":"120363000000000011@g.us"}},"group":{"summary":"Picture of a group you belong to","description":"`Phone` also accepts a group JID.","value":{"Phone":"120363000000000011@g.us","Preview":false}},"group_invite":{"summary":"Group picture before joining","description":"Reads the picture of a group you are not in, authorized by its invite code.","value":{"Phone":"120363000000000011@g.us","Preview":true,"InviteCode":"AbCdEfGhIjKlMnOpQrStUv"}},"community":{"summary":"Community picture","description":"Full picture of a community parent group.","value":{"Phone":"120363000000000022@g.us","Preview":false,"IsCommunity":true}}}}}},"responses":{"200":{"description":"Profile picture metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserAvatarResponse"},"example":{"code":200,"data":{"url":"https://pps.whatsapp.net/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2","id":"1700000000","type":"preview","direct_path":"/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2","hash":null},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `Phone` missing, or `Phone`/`CommonGID` is not a valid JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone":{"summary":"Phone missing","value":{"code":400,"error":"missing Phone in Payload","success":false}},"invalid_phone":{"summary":"Phone is not a valid number or JID","value":{"code":400,"error":"could not parse Phone","success":false}},"invalid_common_gid":{"summary":"CommonGID is not a valid JID","value":{"code":400,"error":"could not parse CommonGID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, no picture set, picture hidden by privacy, or another WhatsApp failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_set":{"summary":"No profile picture (alternate WhatsApp answer)","value":{"code":500,"error":"failed to get avatar: that user or group does not have a profile picture","success":false}},"hidden":{"summary":"Picture hidden by the contact's privacy settings","value":{"code":500,"error":"failed to get avatar: the user has hidden their profile picture from you","success":false}},"no_avatar_found":{"summary":"The contact or group has no profile photo","description":"Usual response when the account or group has no profile photo set.","value":{"code":500,"error":"no avatar found","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/photo":{"post":{"tags":["User"],"summary":"Set your own profile photo","description":"Sets or replaces the profile photo of the connected WhatsApp account. The change is visible to everyone allowed by your profile photo privacy setting.\n\n**Rules:**\n- `Image` is required: a base64 data URL (`data:image/jpeg;base64,...`) or an `http(s)` URL that the gateway downloads.\n- The decoded bytes must be a JPEG image (checked by its file signature); PNG, WebP and other formats return **400**.\n- Square images up to 640x640 px are recommended; WhatsApp may reject very large images.\n\n**Response quirk:**\n- When WhatsApp rejects the upload, the response has HTTP **500** but the legacy body `success: true` with the error text in `data` (no `error` field). Check the HTTP status, not `success`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetProfilePhoto"},"examples":{"base64":{"summary":"JPEG as a base64 data URL","description":"The data URL must carry JPEG bytes; the media type in the prefix is not checked, the bytes are.","value":{"Image":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAD8AKp//2Q=="}},"url":{"summary":"JPEG downloaded from a URL","description":"The gateway downloads the file and validates the JPEG signature before uploading it.","value":{"Image":"https://example.com/images/profile.jpg"}}}}}},"responses":{"200":{"description":"Profile photo updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPhotoResponse"},"example":{"code":200,"data":{"Details":"Profile photo set successfully","PictureID":"1757862000"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `Image` missing or not a data URL/URL, download failure, empty data, or non-JPEG image.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_image":{"summary":"Image missing","value":{"code":400,"error":"missing Image in Payload","success":false}},"unsupported_input":{"summary":"Image is neither a data URL nor an HTTP(S) URL","value":{"code":400,"error":"Image must be a base64 data URL (\"data:image/jpeg;base64,...\") or an HTTP/HTTPS URL","success":false}},"download_failed":{"summary":"The URL could not be downloaded","value":{"code":400,"error":"could not download image from URL: HTTP error 404 when downloading from URL","success":false}},"bad_base64":{"summary":"Invalid base64 in the data URL","value":{"code":400,"error":"could not decode base64 encoded data from payload","success":false}},"empty_image":{"summary":"Data URL without bytes","value":{"code":400,"error":"no image data found in payload","success":false}},"not_jpeg":{"summary":"Image is not JPEG","value":{"code":400,"error":"image must be in JPEG format. WhatsApp only accepts JPEG images for profile photos","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (standard error body), or WhatsApp rejected the photo (legacy body with `success: true` and the message in `data`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"upload_rejected_legacy":{"summary":"WhatsApp rejected the photo (legacy body)","value":{"code":500,"data":"failed to set profile photo: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/photo/remove":{"post":{"tags":["User"],"summary":"Remove your own profile photo","description":"Removes the profile photo of the connected WhatsApp account; contacts then see the default placeholder avatar.\n\n**Rules:**\n- No request body is read.\n- Removing when no photo is set is forwarded to WhatsApp as is.\n\n**Response quirk:**\n- When WhatsApp rejects the removal, the response has HTTP **500** but the legacy body `success: true` with the error text in `data` (no `error` field). Check the HTTP status, not `success`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Profile photo removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserPhotoRemoveResponse"},"example":{"code":200,"data":{"Details":"Profile photo removed successfully"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (standard error body), or WhatsApp rejected the removal (legacy body with `success: true` and the message in `data`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"removal_rejected_legacy":{"summary":"WhatsApp rejected the removal (legacy body)","value":{"code":500,"data":"failed to remove profile photo: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/contacts":{"get":{"tags":["User"],"summary":"List saved contacts","description":"Lists every contact kept in the local contact store of the session: saved address-book names, push names, business names and usernames learned from app state and messages.\n\n**Rules:**\n- No parameters. Data comes from the local store; WhatsApp is not queried.\n- The session must be paired (**500** `not logged in`); an empty store returns **200** with an empty object.\n\n**Response:**\n- `data` is an object keyed by JID (phone JIDs and LIDs can both appear).\n- `RedactedPhone` is only filled for LID members seen in groups, in the masked form WhatsApp shows (for example `+55∙∙∙∙∙∙∙∙99`).\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Contacts keyed by JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactsResponse"},"example":{"code":200,"data":{"5511999999999@s.whatsapp.net":{"Found":true,"FirstName":"Maria","FullName":"Maria Silva","PushName":"Maria","BusinessName":"","Username":"","RedactedPhone":""},"123456789012346@lid":{"Found":true,"FirstName":"","FullName":"","PushName":"Example Store","BusinessName":"Example Store","Username":"examplestore","RedactedPhone":"+55∙∙∙∙∙∙∙∙88"}},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, session not paired, or the contact store failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_logged_in":{"summary":"Session not paired yet","value":{"code":500,"error":"not logged in","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/lid/get":{"get":{"tags":["User LID"],"summary":"Look up the LID of a phone number (query string)","description":"Looks up, in the local LID store of this session, the LID mapped to a phone number or phone JID. Use this GET form when the number fits in the query string.\n\n**Rules:**\n- Pass the number in the `phone` query parameter. Without it the handler tries to read a JSON body, and a GET without body fails with `Invalid JSON format`.\n- `phone` accepts a number with country code (a leading `+` is stripped) or a phone JID. A value that is already a LID returns **400**.\n- Only the local store is consulted; WhatsApp is not queried. An unknown number returns **200** with `has_lid: false`.\n\n**Response quirk:**\n- Validation and store errors of this endpoint use a legacy body: the HTTP status is 400/500 but the body has `success: true` and the message in `data.error`. Check the HTTP status.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"phone","in":"query","required":false,"description":"Phone number with country code, or phone JID. Required unless a JSON body with `phone` is sent.","schema":{"type":"string"},"example":"5511999999999"}],"responses":{"200":{"description":"Lookup result; `has_lid` tells whether a mapping exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLIDGetResponse"},"examples":{"mapped":{"summary":"Mapping found","value":{"code":200,"data":{"success":true,"phone":"5511999999999@s.whatsapp.net","lid":"123456789012345@lid","has_lid":true},"success":true}},"not_mapped":{"summary":"No mapping stored yet","value":{"code":200,"data":{"success":true,"phone":"5511977777777@s.whatsapp.net","lid":"","has_lid":false},"success":true}}}}}},"400":{"description":"Bad Request (legacy body): `phone` missing, unparseable, or already a LID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"no_phone_no_body":{"summary":"No phone query parameter and no JSON body","value":{"code":400,"data":{"error":"Invalid JSON format"},"success":true}},"phone_required":{"summary":"Body sent without phone","value":{"code":400,"data":{"error":"Phone parameter is required"},"success":true}},"unparseable":{"summary":"phone is not a valid number or JID","value":{"code":400,"data":{"error":"Could not parse phone number or JID"},"success":true}},"already_lid":{"summary":"phone is already a LID","value":{"code":400,"data":{"error":"Provided identifier is already a LID, not a phone number"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (legacy body): no WhatsApp session, or the LID store query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"no_client":{"summary":"No WhatsApp session for this user","value":{"code":500,"data":{"error":"WhatsApp client not found"},"success":true}},"store_failed":{"summary":"LID store query failed","value":{"code":500,"data":{"error":"Failed to get LID: sql: database is closed"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"post":{"tags":["User LID"],"summary":"Look up the LID of a phone number (JSON body)","description":"Looks up, in the local LID store of this session, the LID mapped to a phone number or phone JID, taking the number from a JSON body. Behaves like the GET form; use it when your client prefers POST bodies.\n\n**Rules:**\n- Send `phone` in the body. If the `phone` query parameter is also present, the query value wins and the body is not read.\n- `phone` accepts a number with country code (a leading `+` is stripped) or a phone JID. A value that is already a LID returns **400**.\n- Only the local store is consulted; an unknown number returns **200** with `has_lid: false`.\n\n**Response quirk:**\n- Validation and store errors use a legacy body with `success: true` and the message in `data.error`, even though the HTTP status is 400/500.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"phone","in":"query","required":false,"description":"Optional override. When present, it is used instead of the body `phone`.","schema":{"type":"string"},"example":"5511999999999"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetLIDRequest"},"examples":{"number":{"summary":"Phone number","description":"Number with country code, without `+`.","value":{"phone":"5511999999999"}},"jid":{"summary":"Phone JID","description":"A full phone JID is accepted as well.","value":{"phone":"5511999999999@s.whatsapp.net"}}}}}},"responses":{"200":{"description":"Lookup result; `has_lid` tells whether a mapping exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserLIDGetResponse"},"example":{"code":200,"data":{"success":true,"phone":"5511999999999@s.whatsapp.net","lid":"123456789012345@lid","has_lid":true},"success":true}}}},"400":{"description":"Bad Request (legacy body): invalid JSON, `phone` missing, unparseable, or already a LID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"data":{"error":"Invalid JSON format"},"success":true}},"phone_required":{"summary":"phone missing or empty","value":{"code":400,"data":{"error":"Phone parameter is required"},"success":true}},"unparseable":{"summary":"phone is not a valid number or JID","value":{"code":400,"data":{"error":"Could not parse phone number or JID"},"success":true}},"already_lid":{"summary":"phone is already a LID","value":{"code":400,"data":{"error":"Provided identifier is already a LID, not a phone number"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (legacy body): no WhatsApp session, or the LID store query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"no_client":{"summary":"No WhatsApp session for this user","value":{"code":500,"data":{"error":"WhatsApp client not found"},"success":true}},"store_failed":{"summary":"LID store query failed","value":{"code":500,"data":{"error":"Failed to get LID: sql: database is closed"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/lid/from-lid":{"get":{"tags":["User LID"],"summary":"Look up the phone number of a LID (query string)","description":"Translates a LID back to the phone JID using the local LID store of this session. This GET form takes the LID from the query string.\n\n**Rules:**\n- Pass the LID in the `lid` query parameter, including the `@lid` suffix. Without it the handler tries to read a JSON body, and a GET without body fails with `Invalid JSON format`.\n- A value that is not an `@lid` JID returns **400**.\n- Only the local store is consulted; a LID without a stored mapping returns **404**.\n\n**Response quirk:**\n- Every non-401 error uses a legacy body with `success: true` and the message in `data.error`. Check the HTTP status.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"lid","in":"query","required":false,"description":"LID with `@lid` suffix. Required unless a JSON body with `lid` is sent.","schema":{"type":"string"},"example":"123456789012345@lid"}],"responses":{"200":{"description":"Phone JID mapped to the LID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserJIDFromLIDResponse"},"example":{"code":200,"data":{"success":true,"lid":"123456789012345@lid","phone":"5511999999999@s.whatsapp.net"},"success":true}}}},"400":{"description":"Bad Request (legacy body): `lid` missing, malformed, or not an `@lid` JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"no_lid_no_body":{"summary":"No lid query parameter and no JSON body","value":{"code":400,"data":{"error":"Invalid JSON format"},"success":true}},"lid_required":{"summary":"Body sent without lid","value":{"code":400,"data":{"error":"LID parameter is required"},"success":true}},"malformed":{"summary":"lid cannot be parsed as a JID","value":{"code":400,"data":{"error":"Invalid LID format: unexpected number of dots in JID"},"success":true}},"not_lid":{"summary":"lid is a phone JID","value":{"code":400,"data":{"error":"Provided identifier is not a LID"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found (legacy body): the LID has no phone mapping in the local store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":404,"data":{"error":"Phone number not found for this LID"},"success":true}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (legacy body): no WhatsApp session, or the LID store query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"no_client":{"summary":"No WhatsApp session for this user","value":{"code":500,"data":{"error":"WhatsApp client not found"},"success":true}},"store_failed":{"summary":"LID store query failed","value":{"code":500,"data":{"error":"Failed to get phone number: sql: database is closed"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"post":{"tags":["User LID"],"summary":"Look up the phone number of a LID (JSON body)","description":"Translates a LID back to the phone JID using the local LID store of this session, taking the LID from a JSON body. Same result as the GET form.\n\n**Rules:**\n- Send `lid` in the body with the `@lid` suffix. If the `lid` query parameter is also present, the query value wins and the body is not read.\n- A value that is not an `@lid` JID returns **400**; a LID without a stored mapping returns **404**.\n\n**Response quirk:**\n- Every non-401 error uses a legacy body with `success: true` and the message in `data.error`, even though the HTTP status is 400/404/500.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"lid","in":"query","required":false,"description":"Optional override. When present, it is used instead of the body `lid`.","schema":{"type":"string"},"example":"123456789012345@lid"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetJIDFromLIDRequest"},"examples":{"lid":{"summary":"LID from a group participant","description":"LIDs usually come from group events, where members are addressed by LID.","value":{"lid":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"Phone JID mapped to the LID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserJIDFromLIDResponse"},"example":{"code":200,"data":{"success":true,"lid":"123456789012345@lid","phone":"5511999999999@s.whatsapp.net"},"success":true}}}},"400":{"description":"Bad Request (legacy body): invalid JSON, `lid` missing, malformed, or not an `@lid` JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not valid JSON","value":{"code":400,"data":{"error":"Invalid JSON format"},"success":true}},"lid_required":{"summary":"lid missing or empty","value":{"code":400,"data":{"error":"LID parameter is required"},"success":true}},"not_lid":{"summary":"lid is a phone JID","value":{"code":400,"data":{"error":"Provided identifier is not a LID"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found (legacy body): the LID has no phone mapping in the local store.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":404,"data":{"error":"Phone number not found for this LID"},"success":true}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (legacy body): no WhatsApp session, or the LID store query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"no_client":{"summary":"No WhatsApp session for this user","value":{"code":500,"data":{"error":"WhatsApp client not found"},"success":true}},"store_failed":{"summary":"LID store query failed","value":{"code":500,"data":{"error":"Failed to get phone number: sql: database is closed"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/lid/mappings":{"get":{"tags":["User LID"],"summary":"List LID mappings of saved contacts","description":"Lists the phone-to-LID mappings known for the contacts in the local contact store. For each stored contact the gateway looks up its LID and returns the pairs that exist.\n\n**Rules:**\n- No parameters; WhatsApp is not queried.\n- Only contacts present in the contact store are considered, so this is not the complete LID table of the session.\n- The session must be paired (**500** `not logged in`).\n\n**Response:**\n- `mappings` is `null` and `message` is `No LID mappings found` when no pair exists.\n- A missing client and contact-store failures use a legacy error body (`success: true`, message in `data.error`).\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored phone/LID pairs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LIDMappingsResponse"},"examples":{"with_mappings":{"summary":"Mappings found","value":{"code":200,"data":{"success":true,"mappings":[{"lid":"123456789012345@lid","phone":"5511999999999@s.whatsapp.net"},{"lid":"123456789012346@lid","phone":"5511988888888@s.whatsapp.net"}],"count":2},"success":true}},"empty":{"summary":"No mappings yet","value":{"code":200,"data":{"success":true,"mappings":null,"count":0,"message":"No LID mappings found"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: session not paired (standard body), or no client / contact store failure (legacy body).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"not_logged_in":{"summary":"Session not paired yet","value":{"code":500,"error":"not logged in","success":false}},"no_client_legacy":{"summary":"No WhatsApp session for this user (legacy body)","value":{"code":500,"data":{"error":"WhatsApp client not found"},"success":true}},"store_failed_legacy":{"summary":"Contact store failure (legacy body)","value":{"code":500,"data":{"error":"Failed to get contacts: sql: database is closed"},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/delete":{"post":{"tags":["Chat"],"summary":"Delete a message for everyone","description":"Revokes a message so every participant of the chat sees \"This message was deleted\" (delete for everyone).\n\n**Rules:**\n- `Phone` and `Id` are required. `Phone` is the chat: a phone number, a user JID or a group JID.\n- **Own message** (any chat): send only `Phone` and `Id`.\n- **Group admin revoke:** to delete another participant's message in a group, add `Sender` with the original author's JID (`@s.whatsapp.net` or `@lid`). WhatsApp rejects it when this account is not a group admin.\n- WhatsApp enforces its own time window for deleting messages; late revokes fail with **500**.\n- `data.Id` echoes the revoked message ID, not the ID of the revoke protocol message.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDeleteMessageRequest"},"examples":{"own_message":{"summary":"Revoke your own message","description":"Deletes a message this account sent in a direct chat.","value":{"Phone":"5511999999999","Id":"3EB0C767D26A1D6B8A9F"}},"group_admin_revoke":{"summary":"Group admin revokes another member's message","description":"`Sender` is the original author. WhatsApp rejects it when the session is not a group admin.","value":{"Phone":"120363000000000011@g.us","Id":"3EB0C767D26A1D6B8A9E","Sender":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"The revoke was sent and acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDeleteMessageResponse"},"example":{"code":200,"data":{"Details":"Deleted","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2026-09-15T10:30:00-03:00"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `Phone` or `Id` is missing, or `Phone`/`Sender` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone":{"summary":"Phone missing","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_id":{"summary":"Id missing","value":{"code":400,"error":"missing Id in Payload","success":false}},"invalid_phone":{"summary":"Phone cannot be parsed","value":{"code":400,"error":"could not parse Phone","success":false}},"invalid_sender":{"summary":"Sender cannot be parsed","value":{"code":400,"error":"could not parse Sender","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the revoke.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Revoke rejected by the server","value":{"code":500,"error":"error sending message: server returned error 403","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/markread":{"post":{"tags":["Chat"],"summary":"Mark messages as read","description":"Sends a read receipt for one or more messages of a chat, clearing the unread badge on the linked devices and, when privacy allows, showing blue ticks to the sender.\n\n**Rules:**\n- `Id` (array, at least one) and `Chat` are required.\n- `Chat` must be the full chat JID as received in the webhook (`event.Info.Chat`), for example `5511999999999@s.whatsapp.net`, `123456789012345@lid` or `120363000000000011@g.us`. A bare phone number is **not** converted to a JID here; a malformed JID returns **400** `could not decode Payload`.\n- `Sender` (`event.Info.Sender`) is required in groups, where it is sent as the receipt participant; it is ignored for direct chats.\n- All IDs in one call must come from the same sender; call once per sender otherwise.\n\n**Blue ticks:**\n- When this account's `read_receipts` privacy setting is `none`, and always for channels (`@newsletter`), a `read-self` receipt is sent instead: the chat is marked as read on your own devices but no blue ticks are shown. The call still returns 200.\n- A 200 means the receipt was handed to WhatsApp; there is no delivery confirmation.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatMarkReadRequest"},"examples":{"direct_chat":{"summary":"Mark two messages of a direct chat as read","description":"`Sender` is not needed for direct chats.","value":{"Id":["3EB0C767D26A1D6B8A9F","3EB0A1B2C3D4E5F60718"],"Chat":"5511999999999@s.whatsapp.net"}},"group_chat":{"summary":"Mark a group message as read","description":"In groups `Sender` is required and identifies the author of the messages.","value":{"Id":["3EB0C767D26A1D6B8A9F"],"Chat":"120363000000000011@g.us","Sender":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"The read receipt was sent to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatMarkReadResponse"},"example":{"code":200,"data":{"Details":"Message(s) marked as read"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON (or a JID is malformed), `Chat` is missing, or `Id` is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON or a JID is malformed","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_chat":{"summary":"Chat missing","value":{"code":400,"error":"missing Chat in Payload","success":false}},"missing_id":{"summary":"Id empty or missing","value":{"code":400,"error":"missing Id in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the receipt could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Receipt could not be sent","value":{"code":500,"error":"failure marking messages as read","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/react":{"post":{"tags":["Chat"],"summary":"React to a message","description":"Sends an emoji reaction to a message, or removes this account's reaction. The reaction is a new message with its own ID that targets the original message key.\n\n**Addressing (iOS and LID):**\n- iOS drops a reaction silently when its target key is not in the same namespace (phone number vs LID) as the stored original message. Android and Web are lenient.\n- Send back what the webhook gave you: `Chat` with `event.Info.Chat` and, in groups, `Sender` with `event.Info.Sender`.\n- When `Chat` is given it is used as both the send destination and the key chat; otherwise `Phone` is used and the library's LID migration realigns the key.\n\n**Rules:**\n- `Phone` and `Id` are required. `Body` is the emoji; an empty `Body` or `\"remove\"` removes the reaction.\n- Prefix `Id` with `me:` when the target message was sent by this account.\n- `Sender` is only used for another participant's message in a group and must be a full JID; an unparsable value is silently ignored.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReactRequest"},"examples":{"private_received":{"summary":"React to a received message in a direct chat","description":"The phone number is enough for direct chats.","value":{"Phone":"5511999999999","Body":"🔥","Id":"2AFA4C0C20D815D8055A"}},"private_own":{"summary":"React to your own message","description":"The `me:` prefix marks the target message as sent by this account.","value":{"Phone":"5511999999999","Body":"👍","Id":"me:3EB07B61F567BC21530C37"}},"private_explicit_lid":{"summary":"Explicit LID addressing via Chat","description":"`Chat` with the webhook `@lid` chat guarantees rendering on iOS.","value":{"Phone":"5511999999999","Chat":"123456789012345@lid","Body":"👏","Id":"2AFA4C0C20D815D8055A"}},"group_other_member":{"summary":"React to another member's group message","description":"`Sender` carries the author from the webhook (`event.Info.Sender`).","value":{"Phone":"120363000000000011@g.us","Body":"❤️","Id":"2A565EE7389E4B787A9B","Sender":"123456789012345@lid"}},"remove":{"summary":"Remove a reaction","description":"An empty `Body` (or `\"remove\"`) clears this account's reaction.","value":{"Phone":"5511999999999","Body":"remove","Id":"2AFA4C0C20D815D8055A"}}}}}},"responses":{"200":{"description":"The reaction was sent and acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReactResponse"},"example":{"code":200,"data":{"Details":"Sent","Id":"3EB0D1E2F3A4B5C6D7E8","Timestamp":"2026-09-15T10:30:00-03:00"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `Id` or `Phone` is missing, or `Phone`/`Chat` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_fields":{"summary":"Id or Phone missing","value":{"code":400,"error":"id and phone are required","success":false}},"invalid_phone":{"summary":"Phone cannot be parsed","value":{"code":400,"error":"could not parse phone number","success":false}},"invalid_chat":{"summary":"Chat cannot be parsed","value":{"code":400,"error":"could not parse chat JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the reaction could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Reaction could not be sent","value":{"code":500,"error":"error sending reaction: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/text":{"post":{"tags":["Send"],"summary":"Sends a text message","description":"Sends a plain text message to a contact, group or channel.\n\n**Features:**\n- Optional custom `Id`; a random ID is generated otherwise\n- Typing indicator (`Presence`, in ms) before sending\n- Disappearing messages (`Duration`: 86400, 604800 or 7776000 seconds)\n- Automatic link preview (`LinkPreview: true`) and number check (`NumberCheck: true`)\n\n**Rules:**\n- `Phone` and `Body` are required\n- Replies: send `ContextInfo.stanzaID` (message being replied to) together with `ContextInfo.participant` (its author)\n- Add `ContextInfo.quotedMessage` with the original content for a full reply preview on every device; without it the reply works but the preview may be missing\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageText"},"examples":{"simple":{"summary":"Simple text","description":"Sends a text message with a generated ID.","value":{"Phone":"5511999999999","Body":"Hello! Your order has shipped."}},"reply_with_preview":{"summary":"Reply with full quote preview","description":"Replies to a message and includes `quotedMessage` so every device shows the preview.","value":{"Phone":"5511999999999","Body":"This is my reply to your message","ContextInfo":{"stanzaID":"3EB06F9067F80BAB89FF","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"Original message text being replied to"}}}},"typing_link_preview":{"summary":"Typing indicator, link preview and disappearing timer","description":"Shows typing for 3 s, generates a link preview, checks the number and sets a 24 h timer.","value":{"Phone":"5511999999999","Body":"Track your order at https://example.com/orders/1234","Id":"3EB0C767D26A1D6B8A9F","Presence":3000,"Duration":86400,"LinkPreview":true,"NumberCheck":true}}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Body in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_body_in_payload":{"summary":"missing Body in Payload","value":{"code":400,"error":"missing Body in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/link":{"post":{"tags":["Send"],"summary":"Send a link message with optional preview override.","description":"Sends a text message containing a link, with an automatic, customized or disabled preview card.\n\n**Features:**\n- Default: the preview (title, description, image) is scraped from the URL's OpenGraph tags\n- `DisablePreview: true` sends the link as plain text without a card\n- `Preview` with `fetch_missing` omitted/false: REPLACE mode, only the fields you set are used and nothing is scraped\n- `Preview` with `fetch_missing: true`: MERGE mode, the URL is scraped first and non-empty override fields win\n- Captions, mentions, replies and forwarding via `ContextInfo`\n- `AppendLink: false` (alias `append_link`) sends `Caption` exactly as supplied, preserving spaces, line breaks and the link's position; omitted/true keeps the existing append behavior\n- With `AppendLink: false`, a nonblank `Caption` is required. When the preview is enabled, it must contain `Link` or `Preview.matched_text` literally. `Preview.matched_text` counts only when it is an http(s) URL present in the text (WhatsApp ignores plain words such as \"click here\" and drops the card); otherwise `Link` is used, and a caption without `Link` is rejected before sending\n- For an image-only card, set `Preview.image`, omit `title`/`description`, and keep `fetch_missing: false` so the website's metadata is not scraped. WhatsApp does not render a thumbnail card without a title, so whenever an image is sent without one the title falls back to the domain (without `www.`) of the effective match: `Preview.matched_text` when it is a URL found in the text, otherwise `Link`. The response's `Metadata.Title` reports the title actually sent\n\n**Custom thumbnail (`Preview.image`):**\n- Base64 data URL (≤ 5 MB) or http(s) URL (≤ 8 MB); PNG, WebP and GIF are re-encoded to JPEG (transparency flattened on white)\n- For identical cards on mobile and Web/Desktop use a 1.91:1 landscape JPEG, ideally 1200 × 630 px (at least ~400 px on the long edge)\n- The server uploads a high-res JPEG (downscaled to 800 px) and embeds a small inline JPEG (~200 px); Web paints the inline one first\n- Square images of 200 px or less are treated as favicons (smaller card)\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageLink"},"examples":{"auto-scrape":{"summary":"Auto-scraped preview (default)","description":"No `Preview` and no `DisablePreview`: the gateway scrapes the URL's OpenGraph tags. Works for public sites with valid metadata.","value":{"Phone":"5511999999999","Link":"https://github.com/tulir/whatsmeow","Caption":"Check out this WhatsApp library","Id":"ABCDABCD1234"}},"custom-preview-replace":{"summary":"Custom preview (REPLACE, no scrape)","description":"Full override: only the fields set in `Preview` are used and the URL is not fetched. Ideal for coupon links, trackers and URLs without OpenGraph.","value":{"Phone":"5511999999999","Link":"https://example.com/promo","Caption":"Check out this deal","Id":"ABCDABCD1234","Preview":{"title":"Coupon: 50% off everything","description":"Use code SAVE50 at checkout","image":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","matched_text":"https://example.com/promo","type":"image"}}},"template-image-only":{"summary":"Keep the template unchanged with an image-only preview","description":"The URL stays in the middle of the caption without being appended again. Nothing is fetched from the website; the card shows the image with the link's domain as its title.","value":{"Phone":"5511999999999","Link":"https://example.com/promo","Caption":"Confira a oferta!\nhttps://example.com/promo\nUse o cupom SAVE50.","AppendLink":false,"Preview":{"image":"https://example.com/promo.jpg","matched_text":"https://example.com/promo","type":"image","fetch_missing":false}}},"custom-preview-merge":{"summary":"Custom preview (MERGE, scrape + override)","description":"Auto-fetch first; then the non-empty `Preview` fields overwrite the scraped result. Useful to fix only the title/image while keeping the rest.","value":{"Phone":"5511999999999","Link":"https://github.com/tulir/whatsmeow","Id":"ABCDABCD1234","Preview":{"title":"🚀 Custom title overrides the scraped one","fetch_missing":true}}},"image-url-preview":{"summary":"Custom preview with an image URL","description":"Same as REPLACE, but the card image is downloaded server-side from a public URL (≤ 8 MB) instead of base64.","value":{"Phone":"5511999999999","Link":"https://example.com/article","Id":"ABCDABCD1234","Preview":{"title":"Blog article","description":"Summary of the content","image":"https://picsum.photos/seed/zigzapy/600/315","type":"image"}}},"video-preview":{"summary":"Video preview card","description":"Video-type preview card. WhatsApp tries to play it inline unless `do_not_play_inline: true`.","value":{"Phone":"5511999999999","Link":"https://www.youtube.com/watch?v=dQw4w9WgXcQ","Caption":"🎬","Id":"ABCDABCD1234","Preview":{"title":"Never Gonna Give You Up","description":"Rick Astley — official video","image":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","type":"video","do_not_play_inline":false}}},"disable-preview":{"summary":"No preview (plain text)","description":"Sends the link as plain text without a card. Auto-scrape is skipped; `Preview`, if sent, is ignored.","value":{"Phone":"5511999999999","Link":"https://internal.example.com/sensitive-tracker?uid=abc123","Caption":"Internal link (no preview)","Id":"ABCDABCD1234","DisablePreview":true}},"reply-with-preview":{"summary":"Reply with a custom preview","description":"Combines a quote (`ContextInfo.stanzaID`) with a custom preview card.","value":{"Phone":"5511999999999","Link":"https://example.com/promo","Id":"ABCDABCD1234","Preview":{"title":"Reply with link","description":"Custom reply card","type":"placeholder"},"ContextInfo":{"stanzaID":"3EB06F9067F80BAB89FF","participant":"5511999999999@s.whatsapp.net"}}}}}}},"responses":{"200":{"description":"The link message was sent. `data` echoes the link and the preview metadata actually used.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendLinkResult"}]}}}]},"examples":{"sent":{"summary":"Link sent with a scraped preview","value":{"code":200,"data":{"Details":"Link message sent successfully","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2026-09-22T12:49:08-03:00","Link":"https://github.com/tulir/whatsmeow","Metadata":{"Title":"GitHub - tulir/whatsmeow: Go library for the WhatsApp web multidevice API","Description":"Go library for the WhatsApp web multidevice API","Image":"https://opengraph.githubassets.com/1/tulir/whatsmeow","MatchedText":"https://github.com/tulir/whatsmeow","PreviewType":"NONE","PreviewMode":"fetch"}},"success":true}},"image_only_domain_title":{"summary":"Image-only preview (domain used as title)","description":"`Preview.image` without `title`: the domain of the effective match (`matched_text` URL, otherwise `Link`) is sent as the title and reported in `Metadata.Title`.","value":{"code":200,"data":{"Details":"Link message sent successfully","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2026-09-22T12:49:08-03:00","Link":"https://example.com/promo","Metadata":{"Title":"example.com","Description":"","Image":"https://example.com/promo.jpg","MatchedText":"https://example.com/promo","PreviewType":"NONE","PreviewMode":"replace"}},"success":true}},"preview_disabled":{"summary":"Preview disabled","value":{"code":200,"data":{"Details":"Link message sent successfully","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2026-09-22T12:49:08-03:00","Link":"https://internal.example.com/sensitive-tracker?uid=abc123","Metadata":{"Title":"","Description":"","Image":"","MatchedText":"https://internal.example.com/sensitive-tracker?uid=abc123","PreviewType":"","PreviewMode":"disabled"}},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode payload`\n- `missing Phone in payload`\n- `missing Link in payload`\n- `invalid URL format`\n- `invalid preview.type: must be 'image', 'video', 'none', or 'placeholder'`\n- `caption must not be empty when AppendLink is false`\n- `caption must contain Link or preview.matched_text when AppendLink is false and preview is enabled`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode payload","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in payload","value":{"code":400,"error":"missing Phone in payload","success":false}},"missing_link_in_payload":{"summary":"missing Link in payload","value":{"code":400,"error":"missing Link in payload","success":false}},"invalid_url_format":{"summary":"invalid URL format","value":{"code":400,"error":"invalid URL format","success":false}},"unknown_preview_type":{"summary":"Unknown preview type","value":{"code":400,"error":"invalid preview.type: must be 'image', 'video', 'none', or 'placeholder'","success":false}},"append_link_false_empty_caption":{"summary":"AppendLink: false with an empty Caption","value":{"code":400,"error":"caption must not be empty when AppendLink is false","success":false}},"append_link_false_caption_without_link":{"summary":"AppendLink: false and Caption does not contain the link","value":{"code":400,"error":"caption must contain Link or preview.matched_text when AppendLink is false and preview is enabled","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error sending link message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"error sending link message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/edit":{"post":{"tags":["Send"],"summary":"Edit an existing message (text or media caption)","description":"Edits a message previously sent by this session, within 15 minutes of sending.\n\n**Features:**\n- Edits the **text** of a text message or the **caption** of an image, video or document\n- The target type is detected automatically from the message `Id`; `Body` carries the new text or caption\n- Captions can be edited on media sent through this API and on media sent from the operator's phone\n\n**Rules:**\n- `Phone`, the message ID (`Id`, or the `MessageID`/`message_id` alias, which takes precedence) and `Body` are required\n- When the ID is unknown to this instance the edit is sent as a text edit\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEdit"},"examples":{"text_edit":{"summary":"Edit the text of a sent message","value":{"Phone":"5511999999999","Id":"3EB0C767D26A1D6B8A9F","Body":"Meeting moved to 3 PM"},"description":"Replaces the text of a message sent by this session."},"caption_edit_message_id":{"summary":"Edit an image caption using the MessageID alias","description":"`MessageID`/`message_id` takes precedence over `Id`. The target type (text, image, video, document) is detected from the remembered message.","value":{"Phone":"120363000000000001@g.us","MessageID":"3EB0C767D26A1D6B8A9F","Body":"Updated price list (valid until Friday)"}},"snake_case_link_preview":{"summary":"snake_case keys with link preview on a text edit","value":{"phone":"5511988888888","message_id":"3EB0C767D26A1D6B8A9F","body":"New link: https://example.com/checkout","link_preview":true},"description":"Edits a text message with snake_case keys and generates a link preview for the new URL."}}}}},"responses":{"200":{"description":"Edit sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2026-09-15T10:30:00-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Body in Payload`\n- `missing Id or MessageID in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_body_in_payload":{"summary":"missing Body in Payload","value":{"code":400,"error":"missing Body in Payload","success":false}},"missing_id_or_messageid_in_payload":{"summary":"missing Id or MessageID in Payload","value":{"code":400,"error":"missing Id or MessageID in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error sending edit message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"error sending edit message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/image":{"post":{"tags":["Send"],"summary":"Sends an image/picture message","description":"Sends an image to a contact, group or channel.\n\n**Media input (`Image`):** a base64 data URL (`data:image/png;base64,...`) or an `http://`/`https://` URL downloaded server-side (30 s timeout, must answer 200). For data URLs the type comes from the data URL header; for URLs it is detected from the content. The detected type must be `image/jpeg`, `image/png`, `image/gif` or `image/webp` (400 `invalid image format. Supported: JPEG, PNG, GIF, WebP`). The bytes must be a decodable image because a 72 px thumbnail is generated (500 otherwise). The handler enforces no size limit; WhatsApp's media limits apply.\n\n**Accepted keys** (either spelling): `phone`/`Phone`, `image`/`Image`, `caption`/`Caption`, `id`/`Id`, `mime_type`/`MimeType`, `presence`/`Presence`, `view_once`/`ViewOnce`, `duration`/`Duration`, `number_check`/`NumberCheck`, `context_info`/`ContextInfo`, plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone` and `Image` are required.\n- `MimeType` only overrides the `mimetype` written in the message; it does not bypass the format check.\n- `presence` (ms) shows a typing indicator and **delays the HTTP response** by that time.\n- `duration` (seconds) is snapped to the nearest of 86400, 604800 or 7776000.\n- `number_check: true` verifies the number first (400 `phone number is not registered on WhatsApp`).\n- Replies: `ContextInfo.stanzaID` and `ContextInfo.participant` must be sent together (400 `missing Participant in ContextInfo`); add `quotedMessage` for a full preview. With the PascalCase `ContextInfo` key the object is only applied when it has `stanzaID` — to mention or forward without replying use `mention_info` (`mentioned_jid`, `mention_all`) or `forward_info.is_forwarded`.\n- Invalid media input returns 400 (`invalid media input: must be either base64 data URL or HTTP(S) URL`, `could not decode base64 data: ...`, `HTTP error 404 when downloading from URL`).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageImage"},"examples":{"url_with_caption":{"summary":"Image from an HTTPS URL with caption","value":{"Phone":"5511999999999","Image":"https://example.com/media/product.jpg","Caption":"Your order is ready for pickup","Id":"3EB0C767D26A1D6B8A9F"},"description":"Downloads the image server-side and sends it with a caption and a custom message ID."},"base64_png":{"summary":"Image as a short base64 data URL","value":{"Phone":"5511999999999","Image":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","Caption":"Test pixel","NumberCheck":true},"description":"Sends a tiny PNG embedded as a data URL after checking that the number is on WhatsApp."},"snake_case_view_once":{"summary":"snake_case keys, view once, typing delay","value":{"phone":"5511988888888","image":"https://example.com/media/receipt.png","view_once":true,"presence":2000,"number_check":true,"EchoApi":true},"description":"Uses snake_case keys, sends as view once and shows a 2 s typing indicator first."},"group_reply_with_mention":{"summary":"Group reply quoting a message and mentioning a member","value":{"Phone":"120363000000000001@g.us","Image":"https://example.com/media/chart.png","Caption":"Here is the chart @5511988888888","ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"Can you share the chart?"}},"mention_info":{"mentioned_jid":["5511988888888@s.whatsapp.net"]}},"description":"Replies to a group message with a full quote preview and mentions a member."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Image in Payload`\n- `invalid image format. Supported: JPEG, PNG, GIF, WebP`\n- `invalid media input: must be either base64 data URL or HTTP(S) URL`\n- `could not decode base64 data:` followed by the base64 decoding error\n- `HTTP error 404 when downloading from URL`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_image_in_payload":{"summary":"missing Image in Payload","value":{"code":400,"error":"missing Image in Payload","success":false}},"unsupported_image_type":{"summary":"Unsupported image type","value":{"code":400,"error":"invalid image format. Supported: JPEG, PNG, GIF, WebP","success":false}},"media_is_neither_data_url_nor_http_s_url":{"summary":"Media is neither data URL nor HTTP(S) URL","value":{"code":400,"error":"invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"invalid_base64_data":{"summary":"Invalid base64 data","value":{"code":400,"error":"could not decode base64 data: illegal base64 data at input byte 12","success":false}},"media_url_returned_404":{"summary":"Media URL returned 404","value":{"code":400,"error":"HTTP error 404 when downloading from URL","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to upload file:` followed by the WhatsApp media upload error\n- `could not decode image for thumbnail preparation:` followed by the image decoding error\n- `Could not create temp file for thumbnail:` followed by the file system error\n- `Failed to encode jpeg:` followed by the JPEG encoding error\n- `Failed to read` followed by the temporary thumbnail path and the read error\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"failed to upload file: failed to refresh media connections: websocket not connected","success":false}},"image_cannot_be_decoded":{"summary":"Image cannot be decoded","value":{"code":500,"error":"could not decode image for thumbnail preparation: image: unknown format","success":false}},"thumbnail_temp_file_failed":{"summary":"Thumbnail temp file failed","value":{"code":500,"error":"Could not create temp file for thumbnail: open /tmp/resized-2718281828.jpg: no space left on device","success":false}},"thumbnail_encoding_failed":{"summary":"Thumbnail encoding failed","value":{"code":500,"error":"Failed to encode jpeg: write /tmp/resized-2718281828.jpg: no space left on device","success":false}},"thumbnail_read_failed":{"summary":"Thumbnail read failed","value":{"code":500,"error":"Failed to read /tmp/resized-2718281828.jpg: unexpected EOF","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/audio":{"post":{"tags":["Send"],"summary":"Sends an audio message","description":"Sends an audio file or a voice note (PTT) to a contact, group or channel.\n\n**Media input (`Audio`):** a base64 data URL (`data:audio/ogg;base64,...`) or an `http://`/`https://` URL downloaded server-side (30 s timeout). Any audio type is accepted; OGG/Opus gives the best voice-note playback.\n\n**Accepted keys** (either spelling): `phone`/`Phone`, `audio`/`Audio`, `caption`/`Caption`, `id`/`Id`, `ptt`/`PTT`, `presence`/`Presence`, `view_once`/`ViewOnce`, `duration`/`Duration`, `number_check`/`NumberCheck`, `context_info`/`ContextInfo`, plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone` and `Audio` are required.\n- `PTT` defaults to **true** (voice note). For PTT a missing, unsupported or `application/octet-stream` type is sent as `audio/ogg; codecs=opus`; Opus content in OGG is always labelled `audio/ogg; codecs=opus`. With `PTT: false` unknown types fall back to `audio/mpeg`.\n- The duration in seconds (1–3600) is computed from the file and a waveform is always generated.\n- `Caption` is accepted but audio messages carry no caption, so it is not delivered.\n- `presence` (ms) shows a **recording audio** indicator and delays the HTTP response by that time.\n- `duration` (seconds) is snapped to 86400, 604800 or 7776000; `number_check: true` verifies the number first.\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together.\n\nThe 200 response adds `Source` (`base64`|`url`), `PTT`, `Type` (`voice_note`|`audio_file`), `Duration` (seconds), `HasWaveform` and the final `MimeType`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageAudio"},"examples":{"voice_note_url":{"summary":"Voice note from an HTTPS URL with recording indicator","value":{"Phone":"5511999999999","Audio":"https://example.com/media/voice-note.ogg","PTT":true,"Presence":2000},"description":"Sends an OGG/Opus file as a voice note (PTT) after a 2 s recording indicator."},"voice_note_base64":{"summary":"Voice note as a short base64 data URL","value":{"Phone":"5511999999999","Audio":"data:audio/ogg;base64,T2dnUwACAAAAAAAAAABK","Id":"3EB0C767D26A1D6B8A9F"},"description":"Sends a short voice note embedded as a data URL with a custom message ID."},"audio_file_snake_case":{"summary":"MP3 sent as an audio file (snake_case keys)","value":{"phone":"5511988888888","audio":"https://example.com/media/podcast-intro.mp3","ptt":false,"number_check":true,"echo_api":true},"description":"Sends an MP3 as a regular audio file (`ptt: false`) and forces an API echo event."},"group_reply":{"summary":"Voice note replying to a group message","value":{"Phone":"120363000000000001@g.us","Audio":"https://example.com/media/reply.ogg","ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"Can you explain by audio?"}}},"description":"Replies to a group message with a voice note quoting the original text."}}}}},"responses":{"200":{"description":"Audio sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Result of a successful send.","allOf":[{"$ref":"#/components/schemas/SendMessageResult"},{"type":"object","properties":{"Duration":{"type":"integer","description":"Detected duration in seconds.","example":7},"HasWaveform":{"type":"boolean","description":"True when a waveform was generated for the voice note.","example":true},"MimeType":{"type":"string","description":"MIME type written in the message.","example":"audio/ogg; codecs=opus"},"PTT":{"type":"boolean","description":"True when sent as a voice note.","example":true},"Source":{"type":"string","description":"Media input kind (`url` or `base64`).","example":"url"},"Type":{"type":"string","description":"`voice_note` or `audio_file`.","example":"voice_note"}}}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Duration":7,"HasWaveform":true,"Id":"3EB0C767D26A1D6B8A9F","MimeType":"audio/ogg; codecs=opus","PTT":true,"Source":"url","Timestamp":"2026-09-15T10:30:00-03:00","Type":"voice_note"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Audio in Payload`\n- `invalid media input: must be either base64 data URL or HTTP(S) URL`\n- `could not decode base64 data:` followed by the base64 decoding error\n- `HTTP error 404 when downloading from URL`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_audio_in_payload":{"summary":"missing Audio in Payload","value":{"code":400,"error":"missing Audio in Payload","success":false}},"media_is_neither_data_url_nor_http_s_url":{"summary":"Media is neither data URL nor HTTP(S) URL","value":{"code":400,"error":"invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"invalid_base64_data":{"summary":"Invalid base64 data","value":{"code":400,"error":"could not decode base64 data: illegal base64 data at input byte 12","success":false}},"media_url_returned_404":{"summary":"Media URL returned 404","value":{"code":400,"error":"HTTP error 404 when downloading from URL","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to upload audio:` followed by the WhatsApp media upload error\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"failed to upload audio: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/document":{"post":{"tags":["Send"],"summary":"Sends a document message","description":"Sends a document (any file type) to a contact, group or channel.\n\n**Media input (`Document`):** a base64 data URL (`data:application/pdf;base64,...`) or an `http://`/`https://` URL downloaded server-side (30 s timeout). No type restriction; the type comes from the data URL header or is detected from the downloaded content. PDFs get page count and a first-page thumbnail when they can be rendered.\n\n**Accepted keys:** `Phone`, `Document`, `FileName`, `Id`, `MimeType` and `Caption` (matched case-insensitively, so `phone`/`document`/`filename` also work — but not `file_name`), `presence`/`Presence`, `duration`/`Duration`, `number_check`/`NumberCheck`, `ContextInfo` (case-insensitive; `context_info` is not read here), plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone`, `Document` and `FileName` are required (`FileName` is what the recipient sees, include the extension).\n- `MimeType` overrides the detected type in the message.\n- `presence` (ms) shows a typing indicator and delays the HTTP response; `duration` is snapped to 86400, 604800 or 7776000; `number_check: true` verifies the number first.\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together; `ContextInfo` is only applied when it has `stanzaID` (use `mention_info`/`forward_info` for mentions or forwarding without a reply).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageDocument"},"examples":{"pdf_url":{"summary":"PDF from an HTTPS URL","value":{"Phone":"5511999999999","Document":"https://example.com/files/invoice-2026-09.pdf","FileName":"invoice-2026-09.pdf","Caption":"Invoice for September"},"description":"Downloads a PDF server-side and sends it with file name and caption."},"pdf_base64":{"summary":"Small PDF as base64 data URL with MIME override","value":{"Phone":"5511999999999","Document":"data:application/pdf;base64,JVBERi0xLjQKJeLjz9MKMSAwIG9iajw8Pj5lbmRvYmoKdHJhaWxlcjw8Pj4KJSVFT0Y=","FileName":"contract.pdf","MimeType":"application/pdf","Id":"3EB0C767D26A1D6B8A9F"},"description":"Sends a small PDF embedded as a data URL and overrides the MIME type."},"group_with_mention":{"summary":"Spreadsheet to a group mentioning a member","value":{"phone":"120363000000000001@g.us","document":"https://example.com/files/report.xlsx","fileName":"report.xlsx","caption":"Monthly report @5511988888888","presence":1500,"mention_info":{"mentioned_jid":["5511988888888@s.whatsapp.net"]}},"description":"Sends a spreadsheet to a group, mentions a member and shows a typing indicator."},"reply":{"summary":"Document replying to a message","value":{"Phone":"5511988888888","Document":"https://example.com/files/terms.pdf","FileName":"terms.pdf","ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"Please send the terms"}}},"description":"Sends a document that quotes the message asking for it."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Document in Payload`\n- `missing FileName in Payload`\n- `invalid media input: must be either base64 data URL or HTTP(S) URL`\n- `could not decode base64 data:` followed by the base64 decoding error\n- `HTTP error 404 when downloading from URL`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_document_in_payload":{"summary":"missing Document in Payload","value":{"code":400,"error":"missing Document in Payload","success":false}},"missing_filename_in_payload":{"summary":"missing FileName in Payload","value":{"code":400,"error":"missing FileName in Payload","success":false}},"media_is_neither_data_url_nor_http_s_url":{"summary":"Media is neither data URL nor HTTP(S) URL","value":{"code":400,"error":"invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"invalid_base64_data":{"summary":"Invalid base64 data","value":{"code":400,"error":"could not decode base64 data: illegal base64 data at input byte 12","success":false}},"media_url_returned_404":{"summary":"Media URL returned 404","value":{"code":400,"error":"HTTP error 404 when downloading from URL","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to upload file:` followed by the WhatsApp media upload error\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"failed to upload file: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/video":{"post":{"tags":["Send"],"summary":"Sends a video message","description":"Sends a video to a contact, group or channel.\n\n**Media input (`Video`):** a base64 data URL (`data:video/mp4;base64,...`) or an `http://`/`https://` URL downloaded server-side (30 s timeout). The detected type must be `video/mp4`, `video/3gpp`, `video/quicktime` or `video/x-ms-asf` (400 `invalid video format. Supported: MP4, 3GP, MOV, ASF`). For reliable playback use H.264 video with AAC audio.\n\n**Accepted keys** (either spelling): `phone`/`Phone`, `video`/`Video`, `caption`/`Caption`, `id`/`Id`, `jpeg_thumbnail`/`JPEGThumbnail`, `mime_type`/`MimeType`, `gif`/`GIF`, `presence`/`Presence`, `view_once`/`ViewOnce`, `duration`/`Duration`, `number_check`/`NumberCheck`, `context_info`/`ContextInfo`, plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone` and `Video` are required.\n- `JPEGThumbnail` is a **plain base64** JPEG (no `data:` prefix). When omitted a thumbnail is generated from the video, falling back to a generic image.\n- The length in seconds is read from MP4 files only.\n- `GIF: true` sends it as a looping GIF (videos longer than 6 s may not display as GIF).\n- `MimeType` only overrides the `mimetype` in the message; it does not bypass the format check.\n- `presence` (ms) shows a typing indicator and delays the HTTP response; `duration` is snapped to 86400, 604800 or 7776000; `number_check: true` verifies the number first.\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together; with the PascalCase `ContextInfo` key the object is only applied when it has `stanzaID` (use `mention_info`/`forward_info` otherwise).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageVideo"},"examples":{"url_with_caption":{"summary":"MP4 from an HTTPS URL with caption","value":{"Phone":"5511999999999","Video":"https://example.com/media/tutorial.mp4","Caption":"Step-by-step setup"},"description":"Downloads an MP4 server-side and sends it with a caption."},"base64_with_thumbnail":{"summary":"Short base64 data URL with explicit thumbnail","value":{"Phone":"5511999999999","Video":"data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDE=","JPEGThumbnail":"/9j/4AAQSkZJRgABAQEASABIAAD/wAARCAABAAEBAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACP/aAAgBAQAAPwAA/9k=","MimeType":"video/mp4"},"description":"Sends a short MP4 embedded as a data URL with an explicit JPEG thumbnail."},"gif_snake_case":{"summary":"Looping GIF-style video (snake_case keys)","value":{"phone":"5511988888888","video":"https://example.com/media/celebration.mp4","gif":true,"view_once":false,"presence":1500,"number_check":true},"description":"Sends a looping GIF-style video using snake_case keys."},"group_reply":{"summary":"Video replying to a group message","value":{"Phone":"120363000000000001@g.us","Video":"https://example.com/media/answer.mp4","Caption":"As requested","ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"Do you have a video of it?"}}},"description":"Replies to a group message with a video."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Video in Payload`\n- `invalid video format. Supported: MP4, 3GP, MOV, ASF`\n- `invalid media input: must be either base64 data URL or HTTP(S) URL`\n- `could not decode base64 data:` followed by the base64 decoding error\n- `HTTP error 404 when downloading from URL`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_video_in_payload":{"summary":"missing Video in Payload","value":{"code":400,"error":"missing Video in Payload","success":false}},"unsupported_video_type":{"summary":"Unsupported video type","value":{"code":400,"error":"invalid video format. Supported: MP4, 3GP, MOV, ASF","success":false}},"media_is_neither_data_url_nor_http_s_url":{"summary":"Media is neither data URL nor HTTP(S) URL","value":{"code":400,"error":"invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"invalid_base64_data":{"summary":"Invalid base64 data","value":{"code":400,"error":"could not decode base64 data: illegal base64 data at input byte 12","success":false}},"media_url_returned_404":{"summary":"Media URL returned 404","value":{"code":400,"error":"HTTP error 404 when downloading from URL","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to upload file:` followed by the WhatsApp media upload error\n- `error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"failed to upload file: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/ptv":{"post":{"tags":["Send"],"summary":"Send a round video note (PTV)","description":"Sends a **PTV** message: the round, auto-playing video note, to a contact, group or channel.\n\n**Rules:**\n- Body: only `Phone` and `Video` (keys matched case-insensitively), plus the optional `EchoApi`/`echoApi`/`echo_api` flag; both are required (`400 missing phone or video`)\n- `Video` is a base64 data URL or an `http://`/`https://` URL downloaded server-side (30 s timeout); errors return `400 error processing video: <reason>`\n- The type is not validated: send a short, square MP4 (H.264/AAC) so the round preview looks right; a JPEG thumbnail is generated from the video\n\n**Not supported:**\n- Caption, custom `Id` (always generated), `presence`, `duration`, `number_check`, replies (`ContextInfo`), mentions and forwarding\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePTV"},"examples":{"url":{"summary":"Video note from an HTTPS URL","value":{"Phone":"5511999999999","Video":"https://example.com/media/hello-note.mp4"},"description":"Downloads a short square MP4 and sends it as a round video note."},"base64":{"summary":"Video note as a short base64 data URL","value":{"phone":"5511999999999","video":"data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDE=","EchoApi":true},"description":"Sends a video note embedded as a data URL and forces an API echo event."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing phone or video`\n- `could not parse Phone`\n- `error processing video:` followed by the media download or decoding error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_or_video":{"summary":"missing phone or video","value":{"code":400,"error":"missing phone or video","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"video_cannot_be_processed":{"summary":"Video cannot be processed","value":{"code":400,"error":"error processing video: HTTP error 404 when downloading from URL","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error uploading video:` followed by the WhatsApp media upload error\n- `Error sending ptv:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"error uploading video: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending ptv: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/sticker":{"post":{"tags":["Send"],"summary":"Sends a sticker message","description":"Sends a sticker to a contact, group or channel.\n\n**Media input (`Sticker`):** a base64 data URL (`data:image/webp;base64,...`) or an `http://`/`https://` URL downloaded server-side (30 s timeout). The detected type must be `image/jpeg`, `image/png`, `image/gif` or `image/webp` (400 `invalid sticker format. Supported: JPEG, PNG, GIF, WebP`). The file is sent **as is** (no conversion or resizing): WhatsApp clients expect a 512×512 WebP, so other formats may not render as a sticker.\n\n**Accepted keys:** `Phone`, `Sticker`, `Id`, `MimeType`, `PngThumbnail` (case-insensitive), `presence`/`Presence`, `number_check`/`NumberCheck`, `ContextInfo` (case-insensitive), plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone` and `Sticker` are required.\n- `PngThumbnail` is a **plain base64** PNG (no `data:` prefix).\n- No `Duration`/`ViewOnce` support on this endpoint.\n- `presence` (ms) shows a typing indicator and delays the HTTP response; `number_check: true` verifies the number first.\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageSticker"},"examples":{"webp_url":{"summary":"WebP sticker from an HTTPS URL","value":{"Phone":"5511999999999","Sticker":"https://example.com/stickers/thumbs-up.webp"},"description":"Downloads a WebP sticker server-side and sends it."},"webp_base64":{"summary":"WebP sticker as a short base64 data URL","value":{"Phone":"5511999999999","Sticker":"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=","MimeType":"image/webp","Id":"3EB0C767D26A1D6B8A9F"},"description":"Sends a WebP sticker embedded as a data URL with a custom message ID."},"group_reply":{"summary":"Sticker replying in a group","value":{"phone":"120363000000000001@g.us","sticker":"https://example.com/stickers/party.webp","number_check":false,"ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"We closed the deal!"}}},"description":"Replies to a group message with a sticker."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Sticker in Payload`\n- `invalid sticker format. Supported: JPEG, PNG, GIF, WebP`\n- `invalid media input: must be either base64 data URL or HTTP(S) URL`\n- `could not decode base64 data:` followed by the base64 decoding error\n- `HTTP error 404 when downloading from URL`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_sticker_in_payload":{"summary":"missing Sticker in Payload","value":{"code":400,"error":"missing Sticker in Payload","success":false}},"unsupported_sticker_type":{"summary":"Unsupported sticker type","value":{"code":400,"error":"invalid sticker format. Supported: JPEG, PNG, GIF, WebP","success":false}},"media_is_neither_data_url_nor_http_s_url":{"summary":"Media is neither data URL nor HTTP(S) URL","value":{"code":400,"error":"invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"invalid_base64_data":{"summary":"Invalid base64 data","value":{"code":400,"error":"could not decode base64 data: illegal base64 data at input byte 12","success":false}},"media_url_returned_404":{"summary":"Media URL returned 404","value":{"code":400,"error":"HTTP error 404 when downloading from URL","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `Failed to upload file:` followed by the WhatsApp media upload error\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"Failed to upload file: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/location":{"post":{"tags":["Send"],"summary":"Send a location pin","description":"Sends a static location (map pin) to a contact or group.\n\n**Accepted keys:** `Phone`, `Latitude`, `Longitude`, `Name`, `Id` (matched case-insensitively, so `latitude`/`longitude` also work), `presence`/`Presence`, `duration`/`Duration`, `number_check`/`NumberCheck`, `ContextInfo` (case-insensitive), plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone`, `Latitude` and `Longitude` are required. Coordinates are decimal degrees (numbers, not strings).\n- A coordinate equal to **exactly 0** is treated as missing (400 `missing Latitude in Payload` / `missing Longitude in Payload`), so points on the Equator or the prime meridian cannot be sent as-is.\n- `Name` is an optional label shown with the pin; there is no separate address field.\n- `Id` sets a custom message ID; otherwise one is generated.\n- `presence` (ms) shows a typing indicator and delays the HTTP response.\n- `duration` is accepted but **not applied** on this endpoint.\n- `number_check: true` verifies the number first.\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together. Mentions via `mention_info`; forwarding via `forward_info.is_forwarded`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageLocation"},"examples":{"basic":{"summary":"Location with a name","value":{"Phone":"5511999999999","Latitude":-23.561414,"Longitude":-46.655881,"Name":"Example Store - Paulista Ave"},"description":"Sends a named location pin."},"lowercase_keys":{"summary":"Lowercase keys with typing delay and number check","value":{"phone":"5511988888888","latitude":-22.951916,"longitude":-43.210487,"name":"Meeting point","presence":1500,"number_check":true},"description":"Uses lowercase keys, checks the number and shows a typing indicator first."},"group_reply":{"summary":"Location replying in a group","value":{"Phone":"120363000000000001@g.us","Latitude":-25.428356,"Longitude":-49.273252,"Name":"Warehouse","ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511988888888@s.whatsapp.net","quotedMessage":{"conversation":"Where do we pick it up?"}}},"description":"Replies to a group question with the pickup location."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Latitude in Payload`\n- `missing Longitude in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_latitude_in_payload":{"summary":"missing Latitude in Payload","value":{"code":400,"error":"missing Latitude in Payload","success":false}},"missing_longitude_in_payload":{"summary":"missing Longitude in Payload","value":{"code":400,"error":"missing Longitude in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/contact":{"post":{"tags":["Send"],"summary":"Send a contact card (vCard)","description":"Sends a contact card to a contact or group. The recipient sees `Name` and can open or save the card.\n\n**Accepted keys:** `Phone`, `Name`, `Vcard`, `Id` (matched case-insensitively), `presence`/`Presence`, `duration`/`Duration`, `number_check`/`NumberCheck`, `ContextInfo` (case-insensitive), plus `mention_info`, `forward_info` and `EchoApi`/`echoApi`/`echo_api`.\n\n**Rules:**\n- `Phone`, `Name` and `Vcard` are required (400 `missing Name in Payload` / `missing Vcard in Payload`).\n- `Name` becomes the card display name. `Vcard` is sent **verbatim** (not validated); use vCard 3.0 with `\\n` line breaks. Add `waid=<number>` to the `TEL` line so WhatsApp links the card to the account (Message/Add buttons).\n- `Id` sets a custom message ID; otherwise one is generated.\n- `presence` (ms) shows a typing indicator and delays the HTTP response.\n- `duration` is accepted but **not applied** on this endpoint.\n- `number_check: true` verifies the number first (400 `phone number is not registered on WhatsApp`).\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together (400 `missing Participant in ContextInfo`). Mentions via `mention_info`; forwarding via `forward_info.is_forwarded`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageContact"},"examples":{"basic":{"summary":"Share a contact with WhatsApp link","value":{"Phone":"5511999999999","Name":"Maria Souza","Vcard":"BEGIN:VCARD\nVERSION:3.0\nN:Souza;Maria;;;\nFN:Maria Souza\nORG:Example Ltda\nTEL;type=CELL;waid=5511988888888:+55 11 98888-8888\nEMAIL;type=INTERNET:maria@example.com\nEND:VCARD"},"description":"Shares a vCard whose `waid` makes the contact open directly in WhatsApp."},"reply_snake_case":{"summary":"Contact card replying to a message, with number check","value":{"phone":"5511977777777","name":"Support Team","vcard":"BEGIN:VCARD\nVERSION:3.0\nFN:Support Team\nTEL;type=WORK;waid=5511988888888:+55 11 98888-8888\nEND:VCARD","number_check":true,"presence":1000,"ContextInfo":{"stanzaID":"3EB0A1B2C3D4E5F60718","participant":"5511977777777@s.whatsapp.net","quotedMessage":{"conversation":"Who can help me?"}}},"description":"Replies with a support contact card using snake_case keys and number check."}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Name in Payload`\n- `missing Vcard in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_name_in_payload":{"summary":"missing Name in Payload","value":{"code":400,"error":"missing Name in Payload","success":false}},"missing_vcard_in_payload":{"summary":"missing Vcard in Payload","value":{"code":400,"error":"missing Vcard in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/list":{"post":{"tags":["Send"],"summary":"Send a list message","description":"Sends a single-select **list message**: a text body plus a button that opens sections of selectable rows. The user's choice arrives later as an incoming `Message` event (`listResponseMessage`) carrying the selected `RowId`.\n\n**Accepted keys** (either spelling): `phone`/`Phone`, `text`/`Text`, `title`/`Title`, `footer`/`Footer`, `buttonText`/`ButtonText`, `sections`/`Sections`, `id`/`Id`, `presence`/`Presence`, `duration`/`Duration`, `number_check`/`NumberCheck`, `context_info`/`ContextInfo`, plus `EchoApi`/`echoApi`/`echo_api`. Section: `title`/`Title`, `rows`/`Rows`. Row: `rowId`/`RowId`/`RowID`, `title`/`Title`, `description`/`Description`.\n\n**Validation (lengths are counted in bytes):**\n- `Phone`, `Text` and `ButtonText` are required (400 `missing Text in Payload`, `missing ButtonText in Payload`).\n- At least one section, and each section needs at least one row (400 `empty Array sections for list message`, `rows can´t be empty`).\n- `Title` ≤ 60 (`title max 60 characters`), `Text` ≤ 1024 (`body max 1024 characters`), `ButtonText` ≤ 20 (`buttonDisplay max 20 characters`), `Footer` ≤ 60 (`footer max 60 characters`), section `Title` ≤ 60.\n- The gateway does not limit the number of sections/rows nor row title/description length; WhatsApp clients apply their own limits. Give every row a unique `RowId`.\n\n**Other rules:**\n- Message ID: when the server has `LICENSE_KEY` set, the ID is `<yyyyMMddHHmmss><last segment of the license key>` and `Id` is **ignored**; otherwise `Id` is used or a random ID is generated.\n- `presence` (ms) shows a typing indicator and delays the HTTP response; `duration` is snapped to 86400, 604800 or 7776000; `number_check: true` verifies the number first.\n- Replies need `ContextInfo.stanzaID` + `ContextInfo.participant` together; `ContextInfo.mention_all` in groups mentions every member.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageList"},"examples":{"product_menu":{"summary":"Plans and services menu","description":"Interactive list with two sections of rows.","value":{"Phone":"5511988888888","Title":"2026 Plans","Text":"See this month's highlights","Footer":"Choose an option below","ButtonText":"See options","Sections":[{"Title":"Available plans","Rows":[{"RowId":"plan_basic","Title":"Basic plan","Description":"Ideal for small teams"},{"RowId":"plan_pro","Title":"Pro plan","Description":"Advanced features and priority support"}]},{"Title":"Additional services","Rows":[{"RowId":"service_consulting","Title":"Consulting","Description":"1:1 sessions with specialists"},{"RowId":"service_training","Title":"Training","Description":"Custom workshops for teams"}]}]}},"restaurant_menu":{"summary":"Restaurant menu in a group","description":"Menu sections and dishes sent to a group.","value":{"Phone":"120363000000000011@g.us","Title":"Weekly special menu","Text":"Select your dish below","Footer":"Open from 11 AM to 11 PM","ButtonText":"Choose a dish","Sections":[{"Title":"Starters","Rows":[{"RowId":"starter_01","Title":"Bruschetta","Description":"Tomato, basil and olive oil"},{"RowId":"starter_02","Title":"Carpaccio","Description":"Thin beef slices with sauce"}]},{"Title":"Main courses","Rows":[{"RowId":"main_01","Title":"Shrimp risotto","Description":"Arborio rice and grilled shrimp"},{"RowId":"main_02","Title":"Filet mignon","Description":"Served with gratin potatoes"}]}]}}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Text in Payload`\n- `missing ButtonText in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n- `rows can´t be empty`\n- `title max 60 characters`\n- `buttonDisplay max 20 characters`\n- `body max 1024 characters`\n- `footer max 60 characters`\n- `empty Array sections for list message`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_text_in_payload":{"summary":"missing Text in Payload","value":{"code":400,"error":"missing Text in Payload","success":false}},"missing_buttontext_in_payload":{"summary":"missing ButtonText in Payload","value":{"code":400,"error":"missing ButtonText in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}},"section_without_rows":{"summary":"Section without rows","value":{"code":400,"error":"rows can´t be empty","success":false}},"title_or_section_title_longer_than_60_characters":{"summary":"Title or section title longer than 60 characters","value":{"code":400,"error":"title max 60 characters","success":false}},"buttontext_longer_than_20_characters":{"summary":"ButtonText longer than 20 characters","value":{"code":400,"error":"buttonDisplay max 20 characters","success":false}},"text_longer_than_1024_characters":{"summary":"Text longer than 1024 characters","value":{"code":400,"error":"body max 1024 characters","success":false}},"footer_longer_than_60_characters":{"summary":"Footer longer than 60 characters","value":{"code":400,"error":"footer max 60 characters","success":false}},"no_sections":{"summary":"No sections","value":{"code":400,"error":"empty Array sections for list message","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/poll":{"post":{"tags":["Send"],"summary":"Sends a Poll to some group","description":"Sends a poll (single or multiple choice) to a group or directly to a contact.\n\n**Features:**\n- Question in `Header` (or its alias `Question`; `Header` wins when both are sent) with at least 2 `Options`\n- `MaxAnswer` limits how many options each participant can choose (default 1)\n- Optional typing indicator (`Presence`), number check, disappearing `Duration`, replies, mentions and forwarding\n\n**Rules:**\n- `Group` (group JID such as `120363000000000011@g.us`) or `Phone` is required (`400 missing Group or Phone in payload`); `Group` wins when both are sent\n- `400 missing Header or Question in payload`, `at least 2 options are required`, `max_answer must be at least 1`, `max_answer cannot be greater than options length (<n>)`\n- Vote from this session with `POST /chat/send/pollvote`\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessagePoll"},"examples":{"group_poll":{"summary":"Poll in a group","description":"Multi-answer poll sent to a group with a typing indicator.","value":{"Group":"120363000000000011@g.us","Header":"What is the best time?","Options":["09:00","14:00","19:00"],"MaxAnswer":2,"Presence":2000,"NumberCheck":true}},"direct_poll":{"summary":"Direct poll to a contact","description":"Single-answer poll sent directly to a contact with a 24 h disappearing timer.","value":{"Phone":"5511988888888","Question":"Would you recommend our support?","Options":["Yes","Maybe","No"],"MaxAnswer":1,"Duration":86400}}}}}},"responses":{"200":{"description":"Response","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of a successful poll send.","properties":{"Details":{"type":"string","description":"Always `Poll sent successfully`.","example":"Poll sent successfully"},"Id":{"type":"string","description":"WhatsApp message ID of the poll.","example":"3EB0C767D26A1D6B8A9F"}}}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Poll sent successfully","Id":"90B2F8B13FAC8A9CF6B06E99C7834DC5"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode payload`\n- `missing Group or Phone in payload`\n- `missing Header or Question in payload`\n- `at least 2 options are required`\n- `max_answer must be at least 1`\n- `max_answer cannot be greater than options length (3)`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode payload","value":{"code":400,"error":"could not decode payload","success":false}},"missing_group_or_phone_in_payload":{"summary":"missing Group or Phone in payload","value":{"code":400,"error":"missing Group or Phone in payload","success":false}},"missing_header_or_question_in_payload":{"summary":"missing Header or Question in payload","value":{"code":400,"error":"missing Header or Question in payload","success":false}},"at_least_2_options_are_required":{"summary":"at least 2 options are required","value":{"code":400,"error":"at least 2 options are required","success":false}},"max_answer_must_be_at_least_1":{"summary":"max_answer must be at least 1","value":{"code":400,"error":"max_answer must be at least 1","success":false}},"max_answer_above_the_number_of_options":{"summary":"max_answer above the number of options","value":{"code":400,"error":"max_answer cannot be greater than options length (3)","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to send poll:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"failed to send poll: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/pollvote":{"post":{"tags":["Send"],"summary":"Vote on a poll","description":"Casts or retracts this session's vote on a poll.\n\n**Rules:**\n- The poll is identified by the message ID of its creation message (`poll_message_id`)\n- Option names must match the poll's options exactly; unknown options are rejected with `400` instead of being sent as an empty vote\n- Multi-select polls accept more than one option, up to the poll's own limit\n- An empty `options: []` array retracts the vote\n- The vote is encrypted with the poll's message secret, so the poll must have been sent or received by this session (`404` otherwise)\n- Polls created before this instance recorded poll creator info cannot be voted on (`409`); a vote is never sent with a guessed identity, which WhatsApp would silently drop\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollVote"},"examples":{"single_choice":{"summary":"Vote on a single-choice poll","value":{"phone":"5511999999999","poll_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","options":["09:00"]},"description":"Votes for one option of a single-choice poll."},"multi_choice":{"summary":"Vote on a multi-select poll","value":{"phone":"120363000000000011@g.us","poll_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","options":["09:00","14:00"]},"description":"Votes for two options of a multi-select poll in a group."},"retract":{"summary":"Retract the vote (empty options)","value":{"phone":"5511999999999","poll_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","options":[]},"description":"Sends an empty options list to retract the previous vote."}}}}},"responses":{"200":{"description":"Vote sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Result of a successful send.","allOf":[{"$ref":"#/components/schemas/SendMessageResult"},{"type":"object","properties":{"Options":{"type":"array","description":"Options voted (empty when the vote was retracted).","items":{"type":"string"},"example":["09:00"]}}}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26B8F4A1C42","Options":["09:00"],"Timestamp":"2026-07-13T18:22:41Z"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing phone in Payload`\n- `missing poll_message_id in Payload`\n- `could not parse Phone`\n- `option \"20:00\" is not one of this poll's options: [09:00 14:00 19:00]`\n- `poll allows at most 1 selected option(s), got 2`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing phone in Payload","value":{"code":400,"error":"missing phone in Payload","success":false}},"missing_poll_message_id_in_payload":{"summary":"missing poll_message_id in Payload","value":{"code":400,"error":"missing poll_message_id in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"unknown_option":{"summary":"Unknown option","value":{"code":400,"error":"option \"20:00\" is not one of this poll's options: [09:00 14:00 19:00]","success":false}},"too_many_options_selected":{"summary":"Too many options selected","value":{"code":400,"error":"poll allows at most 1 selected option(s), got 2","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"The referenced message is unknown to this session. Possible `error` values:\n- `unknown poll_message_id: this session never sent or received that poll`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unknown_poll":{"summary":"Unknown poll","value":{"code":404,"error":"unknown poll_message_id: this session never sent or received that poll","success":false}}}}}},"409":{"description":"The message cannot be answered by this session. Possible `error` values:\n- `this poll predates vote support (its creator info was never recorded) and cannot be voted on`\n- `the poll's message secret is unknown to this session, so its vote cannot be encrypted`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"poll_predates_vote_support":{"summary":"Poll predates vote support","value":{"code":409,"error":"this poll predates vote support (its creator info was never recorded) and cannot be voted on","success":false}},"poll_secret_unknown":{"summary":"Poll secret unknown","value":{"code":409,"error":"the poll's message secret is unknown to this session, so its vote cannot be encrypted","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to load poll metadata`\n- `failed to build poll vote:` followed by the vote encryption error\n- `error sending poll vote:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"failed_to_load_poll_metadata":{"summary":"failed to load poll metadata","value":{"code":500,"error":"failed to load poll metadata","success":false}},"vote_cannot_be_built":{"summary":"Vote cannot be built","value":{"code":500,"error":"failed to build poll vote: original message secret key not found","success":false}},"whatsapp_rejected_the_vote":{"summary":"WhatsApp rejected the vote","value":{"code":500,"error":"error sending poll vote: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/eventresponse":{"post":{"tags":["Send"],"summary":"Respond (RSVP) to a calendar event","description":"Sends an RSVP to a calendar event message.\n\n**Rules:**\n- The event is identified by the message ID of its creation message (`event_message_id`)\n- `response` is `GOING`, `NOT_GOING`, `MAYBE` or `UNKNOWN`; anything else returns `400`. `UNKNOWN` removes a previous RSVP\n- The RSVP is encrypted with the event's message secret, so the event must have been sent or received by this session (`404` otherwise)\n- Events created before this instance recorded event creator info cannot be answered (`409`)\n\n**Guest:**\n- Send `with_guest: true` (alias `WithGuest`) for \"Going with guest\"; the official app sends it as `extraGuestCount=1`\n- The guest only applies to `GOING` and is ignored for other responses; `with_guest` takes precedence over `extra_guest_count`\n- `extra_guest_count` is deprecated but accepted: `0` means no guest and values of 1 or more are sent as one guest; negative values return `400`\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventResponse"},"examples":{"going":{"summary":"Confirm attendance","value":{"phone":"5511999999999","event_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","response":"GOING","with_guest":false},"description":"Confirms attendance without a guest."},"going_with_guest":{"summary":"Going with guest","value":{"phone":"5511999999999","event_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","response":"GOING","with_guest":true},"description":"Confirms attendance with one guest."},"not_going":{"summary":"Decline the invitation","value":{"phone":"5511999999999","event_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","response":"NOT_GOING"},"description":"Declines the event invitation."},"remove":{"summary":"Remove the RSVP (UNKNOWN)","value":{"phone":"5511999999999","event_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","response":"UNKNOWN"},"description":"Removes the previous RSVP by sending `UNKNOWN`."},"legacy_extra_guest_count":{"summary":"Legacy extra_guest_count (deprecated)","value":{"phone":"5511999999999","event_message_id":"90B2F8B13FAC8A9CF6B06E99C7834DC5","response":"GOING","extra_guest_count":1},"description":"Deprecated field: any `extra_guest_count` of 1 or more is sent as a single guest."}}}}},"responses":{"200":{"description":"RSVP sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Result of a successful send.","allOf":[{"$ref":"#/components/schemas/SendMessageResult"},{"type":"object","properties":{"Response":{"type":"string","description":"RSVP sent.","example":"GOING"}}}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26B8F4A1C42","Response":"GOING","Timestamp":"2026-07-13T18:22:41Z"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing phone in Payload`\n- `missing event_message_id in Payload`\n- `missing response in Payload`\n- `extra_guest_count cannot be negative`\n- `could not parse Phone`\n- `response must be one of GOING, NOT_GOING, MAYBE or UNKNOWN`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing phone in Payload","value":{"code":400,"error":"missing phone in Payload","success":false}},"missing_event_message_id_in_payload":{"summary":"missing event_message_id in Payload","value":{"code":400,"error":"missing event_message_id in Payload","success":false}},"missing_response_in_payload":{"summary":"missing response in Payload","value":{"code":400,"error":"missing response in Payload","success":false}},"extra_guest_count_cannot_be_negative":{"summary":"extra_guest_count cannot be negative","value":{"code":400,"error":"extra_guest_count cannot be negative","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"unknown_response_value":{"summary":"Unknown response value","value":{"code":400,"error":"response must be one of GOING, NOT_GOING, MAYBE or UNKNOWN","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"The referenced message is unknown to this session. Possible `error` values:\n- `unknown event_message_id: this session never sent or received that event`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unknown_event":{"summary":"Unknown event","value":{"code":404,"error":"unknown event_message_id: this session never sent or received that event","success":false}}}}}},"409":{"description":"The message cannot be answered by this session. Possible `error` values:\n- `this event predates RSVP support (its creator info was never recorded) and cannot be answered`\n- `the event's message secret is unknown to this session, so its RSVP cannot be encrypted`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"event_predates_rsvp_support":{"summary":"Event predates RSVP support","value":{"code":409,"error":"this event predates RSVP support (its creator info was never recorded) and cannot be answered","success":false}},"event_secret_unknown":{"summary":"Event secret unknown","value":{"code":409,"error":"the event's message secret is unknown to this session, so its RSVP cannot be encrypted","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to load event metadata`\n- `failed to build event response:` followed by the RSVP encryption error\n- `error sending event response:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"failed_to_load_event_metadata":{"summary":"failed to load event metadata","value":{"code":500,"error":"failed to load event metadata","success":false}},"rsvp_cannot_be_built":{"summary":"RSVP cannot be built","value":{"code":500,"error":"failed to build event response: failed to encrypt event response: original message secret key not found","success":false}},"whatsapp_rejected_the_rsvp":{"summary":"WhatsApp rejected the RSVP","value":{"code":500,"error":"error sending event response: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/event":{"post":{"tags":["Send"],"summary":"Send event message","description":"Send calendar event invitation with date, time, location, and description to a WhatsApp contact or group.\nRecipients can add the event to their calendar. Perfect for meetings, appointments, conferences, and scheduled calls.\n\n**Features:**\n- **Event Details**: Name, description, start/end times\n- **Location Support**: GPS coordinates and address\n- **Call Integration**: Schedule video/voice meetings\n- **Guest Management**: Allow additional guests\n- **Cancellation**: Mark events as cancelled\n- **Message Enhancements**: Replies, forwarding, mentions, expiration\n\n**Use Cases:**\n- 📅 Meeting invitations\n- 🎉 Event planning (parties, conferences)\n- 📞 Scheduled calls\n- 🏢 Location-based events\n- ❌ Event cancellations\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageEvent"},"examples":{"business_meeting":{"summary":"Business Meeting","description":"Schedule a business meeting with location","value":{"Phone":"5511999999999","Name":"Weekly Team Sync 📅","Description":"Discussion of project updates, blockers, and next steps","StartTime":2524608000,"EndTime":2556143999,"ExtraGuestsAllowed":true,"IsScheduleCall":true,"Location":{"Name":"Conference Room A, Main Office","DegreesLatitude":-23.5505,"DegreesLongitude":-46.6333},"NumberCheck":true,"ContextInfo":{"MentionedJID":["5511999999999@s.whatsapp.net"]}}},"virtual_event":{"summary":"Virtual Event","description":"Online event without physical location","value":{"Phone":"120363000000000011@g.us","Name":"Product Launch Event 🚀","Description":"Join us for the launch of our new product line","StartTime":1703184000,"EndTime":1703191200,"ExtraGuestsAllowed":true,"IsScheduleCall":true,"MentionInfo":{"MentionAll":true}}}}}}},"responses":{"200":{"description":"Event message sent successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `Could not decode Payload`\n- `Missing phone in Payload`\n- `Missing name in Payload`\n- `Missing start_time in Payload`\n- `Could not parse JID`\n- `Number is not on WhatsApp`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"Could not decode Payload","value":{"code":400,"error":"Could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"Missing phone in Payload","value":{"code":400,"error":"Missing phone in Payload","success":false}},"missing_name_in_payload":{"summary":"Missing name in Payload","value":{"code":400,"error":"Missing name in Payload","success":false}},"missing_start_time_in_payload":{"summary":"Missing start_time in Payload","value":{"code":400,"error":"Missing start_time in Payload","success":false}},"could_not_parse_jid":{"summary":"Could not parse JID","value":{"code":400,"error":"Could not parse JID","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"Number is not on WhatsApp","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `No session`\n- `Failed to check if 5511999999999 is on WhatsApp:` followed by the phone number and the WhatsApp lookup error\n- `Error sending event:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"No session","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":500,"error":"Failed to check if 5511999999999 is on WhatsApp: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending event: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/buttons":{"post":{"tags":["Send"],"summary":"Send interactive buttons message","description":"Send an interactive message with buttons to a WhatsApp contact or group. Supports multiple button types and media headers.\n\n**⚠️ IMPORTANT - Text fields (canonical casing):**\n- Payloads should use `lowerCamelCase` (e.g. `buttonId`, `displayText`) and, where applicable, the optional snake_case fields such as `pix_key`.\n- With a **media header** (`image`/`video`/`document`): put the main content in `caption` or `text`.\n- **Without** media: use `text` or `body`. The handler mirrors one into the other automatically.\n- Media examples use `text` for backend compatibility.\n\n**Supported Button Types:**\n- 🔘 **reply/quick_reply** – quick reply button (returns `buttonId`)\n- 🔗 **url/cta_url** – opens an HTTP(S) link (`url` or `merchant_url`)\n- 📞 **call/cta_call** – starts a voice call (`phone` in E.164 format)\n- 📋 **copy/cta_copy** – copies a code (`code`)\n- 💰 **pix/payment_info** – PIX payment button (`pix_key`, `merchant_name`, `pix_type`, ...)\n- 💳 **review_and_pay** – review and pay with an item list (`items[]`)\n\nA reply/quick_reply button cannot be mixed with other button types in the same message (400 `if a ButtonReply is present, other button types are not allowed`).\n\n**Media Header Support:**\n- 🖼️ `image` – shows an image above the buttons (`image.url` required)\n- 🎥 `video` – shows a short video (`video.url`)\n- 📄 `document` – shows a document (`document.url`)\n\n**Button Configuration:**\nEach button requires `buttonId`, `buttonText.displayText` and `type`.\nAdditional fields depend on the type:\n- **url/cta_url**: `url` or `merchant_url`\n- **call/cta_call**: `phone`\n- **copy/cta_copy**: `code`\n- **pix/payment_info**: `pix_key`, `merchant_name`, `pix_type`, `currency`, `total_value`, `total_offset`\n- **review_and_pay**: `reference_id` and `items[]` with `name`, `quantity`, `amount_value`, `amount_offset`\n\n**Payment Items Structure** (`review_and_pay`):\nEach item must provide `name`, `quantity`, `amount_value`, `amount_offset`.\n\n**Text Fields:**\n- **title**: Required main title (1 to 60 characters). Do not send only spaces: WhatsApp would show an empty header area.\n- **text/body**: Message content (required when there is no media)\n- **footer**: Secondary text (optional)\n- **caption**: Used as the body when sending media\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ButtonsMessage"},"examples":{"pix_payment":{"summary":"PIX payment button","description":"PIX key button using the camelCase/snake_case payload accepted by the API.","value":{"phone":"5511988888888","title":"PIX payment","body":"Scan the QR code to pay with PIX","footer":"Secure instant payment","buttons":[{"buttonId":"pix_btn_1","buttonText":{"displayText":"Pay with PIX"},"type":"pix","pix_key":"11999999999","merchant_name":"Example Store","pix_type":"PHONE"}]}},"review_and_pay":{"summary":"Review and pay","description":"Order review with an item list and PIX payment (amounts in minor units).","value":{"phone":"5511988888888","title":"Review your order","text":"Confirm the items before paying","footer":"Ships within 24 hours after confirmation","buttons":[{"buttonId":"review_pay_btn","buttonText":{"displayText":"Review and pay"},"type":"review_and_pay","pix_key":"11999999999","merchant_name":"Example Store","pix_type":"PHONE","currency":"BRL","total_value":10990,"total_offset":100,"reference_id":"ORDER-2026-001","items":[{"name":"Headphones","quantity":1,"amount_value":7990,"amount_offset":100},{"name":"USB-C cable","quantity":1,"amount_value":1990,"amount_offset":100},{"name":"Express shipping","quantity":1,"amount_value":1000,"amount_offset":100}]}]}},"pix_with_pdf":{"summary":"PIX with a PDF invoice","description":"review_and_pay button with a PDF document header, suited to invoices and bills. Supported pix_type values: CPF, CNPJ, EMAIL, PHONE, EVP (random key).","value":{"phone":"5511988888888","title":"Monthly invoice","text":"Your invoice is available. Pay with PIX.","footer":"Due date: 2026-10-15","document":{"url":"https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"},"buttons":[{"buttonId":"pix_invoice_1","buttonText":{"displayText":"Pay invoice"},"type":"review_and_pay","pix_key":"billing@example.com","merchant_name":"Example Company Ltd","pix_type":"EMAIL","currency":"BRL","total_value":29990,"total_offset":100,"reference_id":"INV-2026-09-001","items":[{"name":"September subscription","quantity":1,"amount_value":24990,"amount_offset":100},{"name":"Service fee","quantity":1,"amount_value":5000,"amount_offset":100}]}]}},"pix_evp":{"summary":"PIX with a random key (EVP)","description":"PIX button with a random EVP key, suited to one-off payments.","value":{"phone":"5511988888888","title":"PIX payment","body":"Copy the PIX key and pay in your banking app","footer":"Secure instant payment","buttons":[{"buttonId":"pix_evp_1","buttonText":{"displayText":"Copy PIX key"},"type":"pix","pix_key":"123e4567-e89b-12d3-a456-426614174000","merchant_name":"Example Store","pix_type":"EVP"}]}},"video_cta_url":{"summary":"Video header with a URL button","description":"Product demo video with a button that opens the offer page.","value":{"phone":"5511988888888","title":"Product demo","text":"Watch the video and buy!","footer":"Instant payment","video":{"url":"https://download.blender.org/durian/trailer/sintel_trailer-480p.mp4"},"buttons":[{"buttonId":"cta_url_1","buttonText":{"displayText":"Open site"},"type":"cta_url","url":"https://example.com/offer"}]}},"document_cta_url":{"summary":"PDF catalog with a URL button","description":"Catalog download with a CTA URL button.","value":{"phone":"5511988888888","title":"Product catalog","text":"Download our catalog","footer":"PDF with every product","document":{"url":"https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf"},"buttons":[{"buttonId":"cta_url_1","buttonText":{"displayText":"Open site"},"type":"cta_url","url":"https://example.com/offer"}]}},"image_quick_reply":{"summary":"Image header with a quick reply","description":"Attendance confirmation using a quick reply button.","value":{"phone":"5511988888888","title":"Confirm your attendance","text":"VIP event on Oct 12 at 8 PM","footer":"Reply below","image":{"url":"https://picsum.photos/600/400.jpg"},"buttons":[{"buttonId":"reply_maybe","buttonText":{"displayText":"Maybe"},"type":"quick_reply"}]}},"multi_action":{"summary":"Copy + URL + call buttons","description":"Mixes copy code, URL and call buttons in one message.","value":{"phone":"5511988888888","title":"Deals of the day","text":"Choose an action below:","footer":"Zigzapy team","buttons":[{"buttonId":"cta_copy_1","buttonText":{"displayText":"Copy coupon"},"type":"cta_copy","code":"COUPON123"},{"buttonId":"cta_url_1","buttonText":{"displayText":"Open site"},"type":"cta_url","url":"https://example.com/offer"},{"buttonId":"cta_call_1","buttonText":{"displayText":"Call sales"},"type":"cta_call","phone":"+5511988888888"}]}}}}}},"responses":{"200":{"description":"Buttons message sent successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n- `button type not found:` followed by the unknown `type` value\n- `button type not specified`\n- `url required`\n- `url example.com/offer is not valid`\n- `text can´t be null`\n- `text max 30 characters`\n- `phone required`\n- `code required`\n- `id required`\n- `BANK is not pix type, valid type: PHONE, CPF, CNPJ, EMAIL and EVP`\n- `error processing media:` followed by the header media download or decoding error\n- `no body text provided`\n- `header can´t be null`\n- `title max 60 characters`\n- `text max 1024 characters`\n- `footer max 1024 characters`\n- `empty Array buttons`\n- `3 buttons is the limit`\n- `if a ButtonReply is present, other button types are not allowed`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}},"unknown_button_type":{"summary":"Unknown button type","value":{"code":400,"error":"button type not found: carousel","success":false}},"button_without_type":{"summary":"Button without type","value":{"code":400,"error":"button type not specified","success":false}},"url_button_without_url":{"summary":"URL button without url","value":{"code":400,"error":"url required","success":false}},"invalid_button_url":{"summary":"Invalid button URL","value":{"code":400,"error":"url example.com/offer is not valid","success":false}},"button_without_displaytext":{"summary":"Button without displayText","value":{"code":400,"error":"text can´t be null","success":false}},"displaytext_longer_than_30_characters":{"summary":"displayText longer than 30 characters","value":{"code":400,"error":"text max 30 characters","success":false}},"call_button_without_phone":{"summary":"Call button without phone","value":{"code":400,"error":"phone required","success":false}},"copy_button_without_code":{"summary":"Copy button without code","value":{"code":400,"error":"code required","success":false}},"reply_button_without_buttonid":{"summary":"Reply button without buttonId","value":{"code":400,"error":"id required","success":false}},"unknown_pix_type":{"summary":"Unknown pix_type","value":{"code":400,"error":"BANK is not pix type, valid type: PHONE, CPF, CNPJ, EMAIL and EVP","success":false}},"header_media_cannot_be_processed":{"summary":"Header media cannot be processed","value":{"code":400,"error":"error processing media: HTTP error 404 when downloading from URL","success":false}},"no_body_text":{"summary":"No body text","value":{"code":400,"error":"no body text provided","success":false}},"empty_title":{"summary":"Empty title","value":{"code":400,"error":"header can´t be null","success":false}},"title_longer_than_60_characters":{"summary":"Title longer than 60 characters","value":{"code":400,"error":"title max 60 characters","success":false}},"body_longer_than_1024_characters":{"summary":"Body longer than 1024 characters","value":{"code":400,"error":"text max 1024 characters","success":false}},"footer_longer_than_1024_characters":{"summary":"Footer longer than 1024 characters","value":{"code":400,"error":"footer max 1024 characters","success":false}},"no_buttons":{"summary":"No buttons","value":{"code":400,"error":"empty Array buttons","success":false}},"more_than_3_buttons":{"summary":"More than 3 buttons","value":{"code":400,"error":"3 buttons is the limit","success":false}},"reply_mixed_with_other_button_types":{"summary":"Reply mixed with other button types","value":{"code":400,"error":"if a ButtonReply is present, other button types are not allowed","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error uploading media:` followed by the WhatsApp media upload error\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"header_upload_failed":{"summary":"Header upload failed","value":{"code":500,"error":"error uploading media: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/flow":{"post":{"tags":["Send"],"summary":"Send native flow interactive message","description":"Sends a WhatsApp Flow (an interactive form) to a contact.\n\n**How to use:**\n- Create the form in the WhatsApp Business app (Tools → Forms)\n- Send that form once from the app to any chat; the message reaches your webhook, where you copy `flow_id` (and the rest of `button_params_json`) and save it\n- Send the form through this endpoint with button `name` `galaxy_message` and the saved `flow_id` inside `button_params_json`\n- Submitted answers arrive at your configured webhook\n\n**Rules:**\n- Replace `flow_id` in the examples with your own form's ID\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlowMessage"},"examples":{"contact_details_form":{"summary":"Customer info form","description":"Asks the contact for name, email, phone and document. Replace flow_id with your form's id.","value":{"phone":"5511999999999","body":"Please send us your details.","message_version":3,"buttons":[{"name":"galaxy_message","button_params_json":"{\"flow_message_version\":\"4\",\"flow_id\":\"1380039803972405\",\"flow_action_payload\":{\"screen\":\"contact_details\",\"data\":{\"full_name_visible\":true,\"phone_number_visible\":true,\"email_visible\":true,\"cpf_or_cnpj_visible\":true,\"delivery_address_visible\":false,\"citizenship_card_visible\":false,\"custom_fields\":[{\"type\":\"TEXT_INPUT\",\"label\":\"Delivery address\"}]}},\"well_version\":\"V700\",\"flow_cta\":\"__localize:FLOWS_COMPLETE_FORM_BUTTON_TITLE\",\"flow_action\":\"navigate\",\"flow_token\":\"Q1VTVE9NRVJfSU5GTw==\",\"form_type\":\"template\"}"}]}},"offer_signup_form":{"summary":"Offer sign-up form","description":"Sign-up form with an offer title and description. Replace flow_id with your form's id.","value":{"phone":"5511999999999","body":"Claim your offer — fill out the form.","message_version":3,"buttons":[{"name":"galaxy_message","button_params_json":"{\"flow_message_version\":\"4\",\"flow_id\":\"2804269256615624\",\"flow_action_payload\":{\"screen\":\"contact_details\",\"data\":{\"full_name_visible\":true,\"phone_number_visible\":true,\"email_visible\":true,\"delivery_address_visible\":false,\"cpf_or_cnpj_visible\":false,\"citizenship_card_visible\":false,\"offer_name\":\"Special offer\",\"offer_description\":\"offer description\"}},\"well_version\":\"V700\",\"flow_cta\":\"__localize:FLOWS_COMPLETE_FORM_BUTTON_TITLE\",\"flow_action\":\"navigate\",\"flow_token\":\"T0ZGRVJfU0lHTlVQ\",\"form_type\":\"template\"}"}]}}}}}},"responses":{"200":{"description":"Flow message sent successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing body text in Payload`\n- `missing Phone in Payload`\n- `at least one button is required`\n- `button name is required`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n- `invalid button name \"flow\": it renders as \"message not compatible\" on the recipient. For a real WhatsApp flow form use name \"galaxy_message\" with buttonParamsJson form_type \"template\". See this endpoint's description for a complete, working example.`\n- `invalid button name \"send form\": native_flow button names are snake_case without spaces (e.g. \"galaxy_message\")`\n- `button params required for 'galaxy_message'`\n- `invalid JSON in button params for button 'galaxy_message'`\n- `invalid JSON in message_params`\n- `error processing header media:` followed by the header media download or decoding error\n- `unsupported header media type:` followed by the unsupported `Header.Media.Type`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_body_text_in_payload":{"summary":"missing body text in Payload","value":{"code":400,"error":"missing body text in Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"at_least_one_button_is_required":{"summary":"at least one button is required","value":{"code":400,"error":"at least one button is required","success":false}},"button_name_is_required":{"summary":"button name is required","value":{"code":400,"error":"button name is required","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}},"button_named_flow":{"summary":"Button named flow","value":{"code":400,"error":"invalid button name \"flow\": it renders as \"message not compatible\" on the recipient. For a real WhatsApp flow form use name \"galaxy_message\" with buttonParamsJson form_type \"template\". See this endpoint's description for a complete, working example.","success":false}},"button_name_with_spaces":{"summary":"Button name with spaces","value":{"code":400,"error":"invalid button name \"send form\": native_flow button names are snake_case without spaces (e.g. \"galaxy_message\")","success":false}},"button_without_params":{"summary":"Button without params","value":{"code":400,"error":"button params required for 'galaxy_message'","success":false}},"invalid_button_params_json":{"summary":"Invalid button params JSON","value":{"code":400,"error":"invalid JSON in button params for button 'galaxy_message'","success":false}},"invalid_message_params_json":{"summary":"Invalid message_params JSON","value":{"code":400,"error":"invalid JSON in message_params","success":false}},"header_media_cannot_be_processed":{"summary":"Header media cannot be processed","value":{"code":400,"error":"error processing header media: HTTP error 404 when downloading from URL","success":false}},"unsupported_header_media_type":{"summary":"Unsupported header media type","value":{"code":400,"error":"unsupported header media type: audio","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `error uploading header media:` followed by the WhatsApp media upload error\n- `Error sending message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"header_upload_failed":{"summary":"Header upload failed","value":{"code":500,"error":"error uploading header media: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/send/carousel":{"post":{"tags":["Send"],"summary":"Send carousel message with multiple cards","description":"Send a carousel message containing multiple scrollable cards. Each card can include media (image, video, document),\ntext content, and interactive buttons. Perfect for product showcases, service catalogs, and multi-option presentations.\n\n**Carousel Structure:**\n- **Phone**: Recipient phone number or group JID (required)\n- **Message**: Introductory message text before carousel (required)\n- **Carousel**: Array of card objects (required, at least 1 card)\n\n**Card Structure:**\nEach card can contain:\n- **Text**: Card body text (required)\n- **MediaUrl**: URL or base64 data URL for media (optional)\n- **MediaType**: Type of media - image, video, or document (required if MediaUrl provided)\n- **Filename**: Document filename (optional, for documents)\n- **Caption**: Media caption text (optional)\n- **Buttons**: Array of button objects (required)\n\n**Button Types:**\n- 🔘 **reply** - Quick reply button (id + label)\n- 🔗 **url** - Opens web link (url + label)\n- 📋 **copy** - Copies code to clipboard (id as code + label)\n- 📞 **call** - Initiates phone call (id as phone + label)\n\n**Button Structure:**\n- **Id**: Button identifier (for reply/copy) or phone number (for call)\n- **Label**: Button display text\n- **Url**: Destination URL (for url type buttons)\n- **Type**: Button type (reply, url, copy, call)\n\n**Media Support:**\n- **Images**: JPEG, PNG, WebP (recommended max 5MB)\n- **Videos**: MP4, 3GP (recommended max 16MB, max 90 seconds)\n- **Documents**: PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT\n\n**Common Use Cases:**\n- 🛍️ Product catalogs with images and buy buttons\n- 🏨 Hotel room options with photos and booking links\n- 🍕 Restaurant menu with dishes and order buttons\n- 🎓 Course offerings with descriptions and enrollment\n- 🏢 Service packages with pricing and contact options\n- 📱 Feature comparisons with specifications\n\n**Best Practices:**\n- Use 2-10 cards per carousel (optimal user experience)\n- Keep card text concise (50-100 characters recommended)\n- Use high-quality images (at least 800x600px)\n- Limit to 1-3 buttons per card\n- Maintain consistent card structure throughout carousel\n\n**Advanced Features:**\n- Context info for replying to messages\n- Mention support for tagging users\n- Forward info for message forwarding\n- Presence and duration control\n- Number validation before sending\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CarouselMessage"},"examples":{"product_catalog":{"summary":"Product Catalog","description":"E-commerce product showcase with images","value":{"Phone":"5511999999999","Message":"Check out our featured products! 🛍️","Carousel":[{"Text":"Premium Wireless Headphones 🎧\n\n• Noise cancellation\n• 30h battery\n• Premium sound\n\n$299.99","MediaUrl":"https://picsum.photos/600/400.jpg","MediaType":"image","Caption":"Best Seller!","Buttons":[{"Id":"buy_headphones","Label":"🛒 Buy Now","Url":"https://store.example.com/headphones","Type":"url"},{"Id":"headphones_details","Label":"ℹ️ Details","Type":"reply"}]},{"Text":"Smart Watch Pro ⌚\n\n• Fitness tracking\n• Heart rate monitor\n• Water resistant\n\n$199.99","MediaUrl":"https://picsum.photos/600/400.jpg","MediaType":"image","Caption":"New Arrival!","Buttons":[{"Id":"buy_watch","Label":"🛒 Buy Now","Url":"https://store.example.com/watch","Type":"url"},{"Id":"watch_details","Label":"ℹ️ Details","Type":"reply"}]},{"Text":"Bluetooth Speaker 🔊\n\n• 360° sound\n• 12h battery\n• Portable design\n\n$79.99","MediaUrl":"https://picsum.photos/600/400.jpg","MediaType":"image","Caption":"Hot Deal!","Buttons":[{"Id":"buy_speaker","Label":"🛒 Buy Now","Url":"https://store.example.com/speaker","Type":"url"},{"Id":"speaker_details","Label":"ℹ️ Details","Type":"reply"}]}]}},"video_carousel":{"summary":"Video Carousel","description":"Product demos with video previews","value":{"Phone":"5511999999999","Message":"Watch our product demonstrations! 🎥","Carousel":[{"Text":"Product Setup Tutorial\n\nLearn how to set up your new device in under 5 minutes","MediaUrl":"https://download.blender.org/durian/trailer/sintel_trailer-480p.mp4","MediaType":"video","Caption":"Quick Setup Guide","Buttons":[{"Id":"PDF_MANUAL_123","Label":"📋 Copy Manual Code","Type":"copy"},{"Id":"full_tutorial","Label":"🎬 Full Tutorial","Url":"https://youtube.com/watch?v=example","Type":"url"}]},{"Text":"Advanced Features Demo\n\nDiscover pro tips and hidden features","MediaUrl":"https://download.blender.org/durian/trailer/sintel_trailer-480p.mp4","MediaType":"video","Caption":"Pro Tips","Buttons":[{"Id":"features_guide","Label":"📖 Feature Guide","Type":"reply"}]}]}}}}}},"responses":{"200":{"description":"Carousel message sent successfully","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/SendMessageResult"}]}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"Details":"Sent","Id":"3EB0C767D26A1D6B8A9F","Timestamp":"2022-04-20T12:49:08-03:00"},"success":true}}}}}},"400":{"description":"The request was rejected before sending. Possible `error` values:\n- `could not read request body`\n- `could not decode Payload`\n- `missing Phone in Payload`\n- `missing Carousel in Payload`\n- `could not parse Phone`\n- `phone number is not registered on WhatsApp`\n- `missing Participant in ContextInfo`\n- `failed to check if user is on WhatsApp:` followed by the WhatsApp lookup error\n- `error processing media:` followed by the card media download or decoding error\n- `invalid media type`\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_read_request_body":{"summary":"could not read request body","value":{"code":400,"error":"could not read request body","success":false}},"could_not_decode_payload":{"summary":"could not decode Payload","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone_in_payload":{"summary":"missing Phone in Payload","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_carousel_in_payload":{"summary":"missing Carousel in Payload","value":{"code":400,"error":"missing Carousel in Payload","success":false}},"could_not_parse_phone":{"summary":"could not parse Phone","value":{"code":400,"error":"could not parse Phone","success":false}},"number_check_failed":{"summary":"Number check failed","value":{"code":400,"error":"phone number is not registered on WhatsApp","success":false}},"reply_without_participant":{"summary":"Reply without participant","value":{"code":400,"error":"missing Participant in ContextInfo","success":false}},"number_check_lookup_failed":{"summary":"Number check lookup failed","value":{"code":400,"error":"failed to check if user is on WhatsApp: websocket not connected","success":false}},"card_media_cannot_be_processed":{"summary":"Card media cannot be processed","value":{"code":400,"error":"error processing media: HTTP error 404 when downloading from URL","success":false}},"unknown_card_media_type":{"summary":"Unknown card media type","value":{"code":400,"error":"invalid media type","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The session is missing, or preparing or sending the message failed. Possible `error` values:\n- `no session`\n- `failed to upload file:` followed by the WhatsApp media upload error\n- `Error sending carousel message:` followed by the WhatsApp send error\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"no session","value":{"code":500,"error":"no session","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"failed to upload file: failed to refresh media connections: websocket not connected","success":false}},"whatsapp_rejected_the_send":{"summary":"WhatsApp rejected the send","value":{"code":500,"error":"Error sending carousel message: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/downloadimage":{"post":{"tags":["Chat"],"summary":"Download the image of a message","description":"Downloads and decrypts the image of a received or sent message and returns the whole file inline as a base64 data URL, ready for an HTML `<img>` tag or to be saved to disk.\n\n**Where the fields come from:** Copy the fields from `event.Message.imageMessage` of the `Message` webhook event (view-once images are nested under `viewOnceMessageV2.message.imageMessage`). Keys are matched case-insensitively and unknown keys are ignored, so that `imageMessage` object can be posted unchanged.\n\n**Rules (image):**\n- `DirectPath`, `MediaKey`, `FileEncSHA256` and `FileSHA256` are what the image download needs; without `DirectPath` it fails with **500** `failed to download image no url present`.\n- The image `MediaKey` and both hashes are standard base64 strings exactly as in the webhook JSON; a value that is not valid base64 returns **400** `could not decode Payload`.\n- A key or hash that does not match the image fails with **500** `failed to download image invalid media hmac` (or a hash mismatch detail); an expired CDN link fails with `download failed with status code 404` or `410`.\n- `Url` and `FileLength` are accepted but not used for the image. `Mimetype` is not validated: it is echoed in the response and used as the image data URL media type.\n- JPEG is the usual format; `Data` starts with `data:image/jpeg;base64,`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaRequest"},"examples":{"image_fields":{"summary":"Fields copied from the webhook imageMessage","description":"Minimal body with the gateway field names.","value":{"Url":"https://mmg.whatsapp.net/o1/v/t62.7118-24/f2/m231/AQ_example_image.enc?ccb=9-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=e6ed6c","DirectPath":"/o1/v/t62.7118-24/f2/m231/AQ_example_image.enc?ccb=9-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=e6ed6c","MediaKey":"aQGcesqhANsFce2gBbNeXnE4LU9wA6LM5lA1ztbBduM=","Mimetype":"image/jpeg","FileEncSHA256":"8wdTCF7kBugCQhneOg2YLsDye4Eqwu7N8kzyXKJXoIU=","FileSHA256":"Gc6NIzcYSI596Ke0Y0sO1VstRgq8FpAUzOglP06aYyE=","FileLength":48213}},"webhook_object_verbatim":{"summary":"Posting event.Message.imageMessage unchanged","description":"Webhook keys (`URL`, `directPath`, `mediaKey`, ...) map case-insensitively to the body fields; extra keys are ignored.","value":{"URL":"https://mmg.whatsapp.net/o1/v/t62.7118-24/f2/m231/AQ_example_image.enc?ccb=9-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=e6ed6c","directPath":"/o1/v/t62.7118-24/f2/m231/AQ_example_image.enc?ccb=9-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=e6ed6c","mediaKey":"aQGcesqhANsFce2gBbNeXnE4LU9wA6LM5lA1ztbBduM=","mimetype":"image/jpeg","fileEncSHA256":"8wdTCF7kBugCQhneOg2YLsDye4Eqwu7N8kzyXKJXoIU=","fileSHA256":"Gc6NIzcYSI596Ke0Y0sO1VstRgq8FpAUzOglP06aYyE=","fileLength":48213,"caption":"Order photo","height":1280,"width":960,"mediaKeyTimestamp":1757862000}}}}}},"responses":{"200":{"description":"The image was downloaded and decrypted; `data.Data` holds the whole file as a data URL (truncated in this example).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaResponse"},"example":{"code":200,"data":{"Mimetype":"image/jpeg","Data":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIy"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `MediaKey`/`FileEncSHA256`/`FileSHA256` is not valid base64.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the per-user files directory could not be created, or the image download/decryption failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"no_url_present":{"summary":"DirectPath missing","value":{"code":500,"error":"failed to download image no url present","success":false}},"invalid_media_hmac":{"summary":"MediaKey does not match the file","value":{"code":500,"error":"failed to download image invalid media hmac","success":false}},"expired_link":{"summary":"CDN link expired","value":{"code":500,"error":"failed to download image download failed with status code 410","success":false}},"user_directory":{"summary":"Files directory could not be created","value":{"code":500,"error":"could not create user directory (/opt/zigzapy/files/user_3f2a9c1d)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/downloadvideo":{"post":{"tags":["Chat"],"summary":"Download the video of a message","description":"Downloads and decrypts the video of a received or sent message and returns the whole file inline as a base64 data URL, ready for an HTML `<video>` tag or to be saved to disk.\n\n**Where the fields come from:** Copy the fields from `event.Message.videoMessage` of the `Message` webhook event (round video notes use the same fields under `ptvMessage`). Keys are matched case-insensitively and unknown keys are ignored, so that `videoMessage` object can be posted unchanged.\n\n**Rules (video):**\n- `DirectPath`, `MediaKey`, `FileEncSHA256` and `FileSHA256` are what the video download needs; without `DirectPath` it fails with **500** `failed to download video no url present`.\n- The video `MediaKey` and both hashes are standard base64 strings exactly as in the webhook JSON; a value that is not valid base64 returns **400** `could not decode Payload`.\n- A key or hash that does not match the video fails with **500** `failed to download video invalid media hmac` (or a hash mismatch detail); an expired CDN link fails with `download failed with status code 404` or `410`.\n- `Url` and `FileLength` are accepted but not used for the video. `Mimetype` is not validated: it is echoed in the response and used as the video data URL media type.\n- The base64 body is about 33% larger than the video itself; prefer S3 media delivery for large videos.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaRequest"},"examples":{"video_fields":{"summary":"Fields copied from the webhook videoMessage","description":"Minimal body with the gateway field names.","value":{"Url":"https://mmg.whatsapp.net/v/t62.7161-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","DirectPath":"/v/t62.7161-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","MediaKey":"TzA1SP0MVnA9QdoPO44ev2R8UVuiAdV+swlmjv3vNMQ=","Mimetype":"video/mp4","FileEncSHA256":"aOLrc4v0IpCOrMrZdkJnbVxl2mjiJ2OiaXbVDHwPja4=","FileSHA256":"qUYqZxL/XODxflh6YPYvdOOLLor5G6E5BkRK+fgSLLY=","FileLength":1843200}},"webhook_object_verbatim":{"summary":"Posting event.Message.videoMessage unchanged","description":"Webhook keys (`URL`, `directPath`, `mediaKey`, ...) map case-insensitively to the body fields; extra keys are ignored.","value":{"URL":"https://mmg.whatsapp.net/v/t62.7161-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","directPath":"/v/t62.7161-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","mediaKey":"TzA1SP0MVnA9QdoPO44ev2R8UVuiAdV+swlmjv3vNMQ=","mimetype":"video/mp4","fileEncSHA256":"aOLrc4v0IpCOrMrZdkJnbVxl2mjiJ2OiaXbVDHwPja4=","fileSHA256":"qUYqZxL/XODxflh6YPYvdOOLLor5G6E5BkRK+fgSLLY=","fileLength":1843200,"seconds":12,"caption":"Unboxing"}}}}}},"responses":{"200":{"description":"The video was downloaded and decrypted; `data.Data` holds the whole file as a data URL (truncated in this example).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaResponse"},"example":{"code":200,"data":{"Mimetype":"video/mp4","Data":"data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAu1tZGF0"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `MediaKey`/`FileEncSHA256`/`FileSHA256` is not valid base64.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the per-user files directory could not be created, or the video download/decryption failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"no_url_present":{"summary":"DirectPath missing","value":{"code":500,"error":"failed to download video no url present","success":false}},"invalid_media_hmac":{"summary":"MediaKey does not match the file","value":{"code":500,"error":"failed to download video invalid media hmac","success":false}},"expired_link":{"summary":"CDN link expired","value":{"code":500,"error":"failed to download video download failed with status code 410","success":false}},"user_directory":{"summary":"Files directory could not be created","value":{"code":500,"error":"could not create user directory (/opt/zigzapy/files/user_3f2a9c1d)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/downloaddocument":{"post":{"tags":["Chat"],"summary":"Download the document of a message","description":"Downloads and decrypts the document of a received or sent message (PDF, spreadsheet, archive or any other file) and returns the whole file inline as a base64 data URL.\n\n**Where the fields come from:** Copy the fields from `event.Message.documentMessage` of the `Message` webhook event, or from `documentWithCaptionMessage.message.documentMessage` when the document has a caption. Keys are matched case-insensitively and unknown keys are ignored, so that `documentMessage` object can be posted unchanged.\n\n**Rules (document):**\n- `DirectPath`, `MediaKey`, `FileEncSHA256` and `FileSHA256` are what the document download needs; without `DirectPath` it fails with **500** `failed to download document no url present`.\n- The document `MediaKey` and both hashes are standard base64 strings exactly as in the webhook JSON; a value that is not valid base64 returns **400** `could not decode Payload`.\n- A key or hash that does not match the document fails with **500** `failed to download document invalid media hmac` (or a hash mismatch detail); an expired CDN link fails with `download failed with status code 404` or `410`.\n- `Url` and `FileLength` are accepted but not used for the document. `Mimetype` is not validated: it is echoed in the response and used as the document data URL media type.\n- The original file name is not returned; keep `fileName` from the webhook event.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaRequest"},"examples":{"document_fields":{"summary":"Fields copied from the webhook documentMessage","description":"Minimal body with the gateway field names.","value":{"Url":"https://mmg.whatsapp.net/v/t62.7119-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","DirectPath":"/v/t62.7119-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","MediaKey":"GKgwzoHzV4RrbwisIF1GdFXTt9RbCHM9vt/5gZ3P8vw=","Mimetype":"application/pdf","FileEncSHA256":"t2yh2iPMW1nkv0t2bf0sP7EH9szzZtpfyzVtfgJ+qrg=","FileSHA256":"E+J9XK+0syXqLfYT9o/C8VgBtytAfz/vC5GFVn1s9dE=","FileLength":254871}},"webhook_object_verbatim":{"summary":"Posting event.Message.documentMessage unchanged","description":"Webhook keys (`URL`, `directPath`, `mediaKey`, ...) map case-insensitively to the body fields; extra keys are ignored.","value":{"URL":"https://mmg.whatsapp.net/v/t62.7119-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","directPath":"/v/t62.7119-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","mediaKey":"GKgwzoHzV4RrbwisIF1GdFXTt9RbCHM9vt/5gZ3P8vw=","mimetype":"application/pdf","fileEncSHA256":"t2yh2iPMW1nkv0t2bf0sP7EH9szzZtpfyzVtfgJ+qrg=","fileSHA256":"E+J9XK+0syXqLfYT9o/C8VgBtytAfz/vC5GFVn1s9dE=","fileLength":254871,"title":"invoice-2026-09","pageCount":2,"fileName":"invoice-2026-09.pdf"}}}}}},"responses":{"200":{"description":"The document was downloaded and decrypted; `data.Data` holds the whole file as a data URL (truncated in this example).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaResponse"},"example":{"code":200,"data":{"Mimetype":"application/pdf","Data":"data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2Jq"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `MediaKey`/`FileEncSHA256`/`FileSHA256` is not valid base64.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the per-user files directory could not be created, or the document download/decryption failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"no_url_present":{"summary":"DirectPath missing","value":{"code":500,"error":"failed to download document no url present","success":false}},"invalid_media_hmac":{"summary":"MediaKey does not match the file","value":{"code":500,"error":"failed to download document invalid media hmac","success":false}},"expired_link":{"summary":"CDN link expired","value":{"code":500,"error":"failed to download document download failed with status code 410","success":false}},"user_directory":{"summary":"Files directory could not be created","value":{"code":500,"error":"could not create user directory (/opt/zigzapy/files/user_3f2a9c1d)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/downloadaudio":{"post":{"tags":["Chat"],"summary":"Download the audio of a message","description":"Downloads and decrypts the audio of a received or sent message (audio file or PTT voice note) and returns the whole file inline as a base64 data URL, ready for an HTML `<audio>` tag or to be saved to disk.\n\n**Where the fields come from:** Copy the fields from `event.Message.audioMessage` of the `Message` webhook event; voice notes carry `PTT: true` there. Keys are matched case-insensitively and unknown keys are ignored, so that `audioMessage` object can be posted unchanged.\n\n**Rules (audio):**\n- `DirectPath`, `MediaKey`, `FileEncSHA256` and `FileSHA256` are what the audio download needs; without `DirectPath` it fails with **500** `failed to download audio no url present`.\n- The audio `MediaKey` and both hashes are standard base64 strings exactly as in the webhook JSON; a value that is not valid base64 returns **400** `could not decode Payload`.\n- A key or hash that does not match the audio fails with **500** `failed to download audio invalid media hmac` (or a hash mismatch detail); an expired CDN link fails with `download failed with status code 404` or `410`.\n- `Url` and `FileLength` are accepted but not used for the audio. `Mimetype` is not validated: it is echoed in the response and used as the audio data URL media type.\n- Voice notes are Ogg/Opus, so `Mimetype` is usually `audio/ogg; codecs=opus`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaRequest"},"examples":{"audio_fields":{"summary":"Fields copied from the webhook audioMessage","description":"Minimal body with the gateway field names.","value":{"Url":"https://mmg.whatsapp.net/v/t62.7117-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","DirectPath":"/v/t62.7117-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","MediaKey":"uYP/0reexMYRve9yzhNYWm1Yg80HpiSawTMxht4AR/8=","Mimetype":"audio/ogg; codecs=opus","FileEncSHA256":"BRZJpqMSy97nxJJBjBgQEqwQWEU345ai++oAw1Kgv/E=","FileSHA256":"ndJ/Uki+LYYxZGn1hgjJATgFIIqT1SUlLQogFvta1mM=","FileLength":18342}},"webhook_object_verbatim":{"summary":"Posting event.Message.audioMessage unchanged","description":"Webhook keys (`URL`, `directPath`, `mediaKey`, ...) map case-insensitively to the body fields; extra keys are ignored.","value":{"URL":"https://mmg.whatsapp.net/v/t62.7117-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","directPath":"/v/t62.7117-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","mediaKey":"uYP/0reexMYRve9yzhNYWm1Yg80HpiSawTMxht4AR/8=","mimetype":"audio/ogg; codecs=opus","fileEncSHA256":"BRZJpqMSy97nxJJBjBgQEqwQWEU345ai++oAw1Kgv/E=","fileSHA256":"ndJ/Uki+LYYxZGn1hgjJATgFIIqT1SUlLQogFvta1mM=","fileLength":18342,"seconds":7,"PTT":true}}}}}},"responses":{"200":{"description":"The audio was downloaded and decrypted; `data.Data` holds the whole file as a data URL (truncated in this example).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaResponse"},"example":{"code":200,"data":{"Mimetype":"audio/ogg; codecs=opus","Data":"data:audio/ogg; codecs=opus;base64,T2dnUwACAAAAAAAAAAAAAAAAAAAAAMhHv8oBE09wdXNIZWFkAQE4AYC7AAAAAABPZ2dT"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `MediaKey`/`FileEncSHA256`/`FileSHA256` is not valid base64.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the per-user files directory could not be created, or the audio download/decryption failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"no_url_present":{"summary":"DirectPath missing","value":{"code":500,"error":"failed to download audio no url present","success":false}},"invalid_media_hmac":{"summary":"MediaKey does not match the file","value":{"code":500,"error":"failed to download audio invalid media hmac","success":false}},"expired_link":{"summary":"CDN link expired","value":{"code":500,"error":"failed to download audio download failed with status code 410","success":false}},"user_directory":{"summary":"Files directory could not be created","value":{"code":500,"error":"could not create user directory (/opt/zigzapy/files/user_3f2a9c1d)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/downloadsticker":{"post":{"tags":["Chat"],"summary":"Download the sticker of a message","description":"Downloads and decrypts the sticker of a received or sent message (static or animated WebP) and returns the whole file inline as a base64 data URL.\n\n**Where the fields come from:** Copy the fields from `event.Message.stickerMessage` of the `Message` webhook event. Keys are matched case-insensitively and unknown keys are ignored, so that `stickerMessage` object can be posted unchanged.\n\n**Rules (sticker):**\n- `DirectPath`, `MediaKey`, `FileEncSHA256` and `FileSHA256` are what the sticker download needs; without `DirectPath` it fails with **500** `failed to download sticker no url present`.\n- The sticker `MediaKey` and both hashes are standard base64 strings exactly as in the webhook JSON; a value that is not valid base64 returns **400** `could not decode Payload`.\n- A key or hash that does not match the sticker fails with **500** `failed to download sticker invalid media hmac` (or a hash mismatch detail); an expired CDN link fails with `download failed with status code 404` or `410`.\n- `Url` and `FileLength` are accepted but not used for the sticker. `Mimetype` is not validated: it is echoed in the response and used as the sticker data URL media type.\n- Items from `GET /business/sticker-pack/{packId}` expose `media_key`, `file_hash` and `file_enc_hash` in hex: convert them to base64 first, otherwise the download fails with `invalid media hmac`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaRequest"},"examples":{"sticker_fields":{"summary":"Fields copied from the webhook stickerMessage","description":"Minimal body with the gateway field names.","value":{"Url":"https://mmg.whatsapp.net/v/t62.15575-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","DirectPath":"/v/t62.15575-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","MediaKey":"ARQlqjgLupJ1vQyWDC5cTv5GKrcuduMvjXJDRgrm2QI=","Mimetype":"image/webp","FileEncSHA256":"THZUjSUStp6pDg8O0OiyCvkufOzScdfzxnucpeuxlMs=","FileSHA256":"CWAdQIgyvMC9mhYAgjQwbChLpbLJ7wPfnSFTiYJo+Qk=","FileLength":21456}},"webhook_object_verbatim":{"summary":"Posting event.Message.stickerMessage unchanged","description":"Webhook keys (`URL`, `directPath`, `mediaKey`, ...) map case-insensitively to the body fields; extra keys are ignored.","value":{"URL":"https://mmg.whatsapp.net/v/t62.15575-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","directPath":"/v/t62.15575-24/11111111_2222222222222222_3333333333333333333_n.enc?ccb=11-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=5e03e0","mediaKey":"ARQlqjgLupJ1vQyWDC5cTv5GKrcuduMvjXJDRgrm2QI=","mimetype":"image/webp","fileEncSHA256":"THZUjSUStp6pDg8O0OiyCvkufOzScdfzxnucpeuxlMs=","fileSHA256":"CWAdQIgyvMC9mhYAgjQwbChLpbLJ7wPfnSFTiYJo+Qk=","fileLength":21456,"height":512,"width":512,"isAnimated":false}}}}}},"responses":{"200":{"description":"The sticker was downloaded and decrypted; `data.Data` holds the whole file as a data URL (truncated in this example).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDownloadMediaResponse"},"example":{"code":200,"data":{"Mimetype":"image/webp","Data":"data:image/webp;base64,UklGRroBAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA="},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `MediaKey`/`FileEncSHA256`/`FileSHA256` is not valid base64.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode Payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the per-user files directory could not be created, or the sticker download/decryption failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"no_url_present":{"summary":"DirectPath missing","value":{"code":500,"error":"failed to download sticker no url present","success":false}},"invalid_media_hmac":{"summary":"MediaKey does not match the file","value":{"code":500,"error":"failed to download sticker invalid media hmac","success":false}},"expired_link":{"summary":"CDN link expired","value":{"code":500,"error":"failed to download sticker download failed with status code 410","success":false}},"user_directory":{"summary":"Files directory could not be created","value":{"code":500,"error":"could not create user directory (/opt/zigzapy/files/user_3f2a9c1d)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/presence":{"post":{"tags":["Chat"],"summary":"Show or clear the typing indicator in a chat","description":"Sends a chat state to a contact or group so they see \"typing…\" or \"recording audio…\", or clears it.\n\n**Rules:**\n- `Phone` and `State` are required. `Phone` accepts a phone number, a user JID or a group JID.\n- `State` is `composing` (indicator on) or `paused` (indicator off). The value is sent as given without validation.\n- `Media: \"audio\"` turns `composing` into \"recording audio…\"; it is ignored for `paused`.\n- WhatsApp clears the indicator by itself after a few seconds, so repeat `composing` during long operations and send `paused` when done.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPresenceStateRequest"},"examples":{"typing":{"summary":"Show typing in a direct chat","description":"The contact sees \"typing…\" for a few seconds.","value":{"Phone":"5511999999999","State":"composing"}},"recording_audio":{"summary":"Show recording audio","description":"`Media: audio` shows the microphone indicator instead of typing.","value":{"Phone":"5511999999999","State":"composing","Media":"audio"}},"stop_in_group":{"summary":"Clear the indicator in a group","description":"`paused` removes the indicator immediately.","value":{"Phone":"120363000000000011@g.us","State":"paused"}}}}}},"responses":{"200":{"description":"The chat state was sent to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPresenceStateResponse"},"example":{"code":200,"data":{"Details":"Chat presence set successfuly"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `Phone` or `State` is missing, or `Phone` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_phone":{"summary":"Phone missing","value":{"code":400,"error":"missing Phone in Payload","success":false}},"missing_state":{"summary":"State missing","value":{"code":400,"error":"missing State in Payload","success":false}},"invalid_phone":{"summary":"Phone cannot be parsed","value":{"code":400,"error":"could not parse Phone","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the chat state could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Chat state could not be sent","value":{"code":500,"error":"failure sending chat presence to Whatsapp servers","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/pin":{"post":{"tags":["Chat"],"summary":"Pin or unpin a chat in the chat list","description":"Pins a chat (contact or group) to the top of the chat list on every linked device, or unpins it, by sending a\n`pin` app-state mutation. To pin a single message inside a conversation use `POST /chat/pin-message`.\n\n**Rules:**\n- `phone` is required; `pin` defaults to `false`, so omitting it unpins the chat.\n- `phone` accepts a phone number, a user JID (`@s.whatsapp.net` / `@lid`) or a group JID (`@g.us`) and is written to the mutation as given.\n- The official apps show at most 3 pinned chats; the gateway does not enforce this limit.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPinRequest"},"examples":{"pin_contact":{"summary":"Pin a contact chat","description":"Moves the direct chat to the top of the chat list.","value":{"phone":"5511999999999","pin":true}},"pin_group":{"summary":"Pin a group chat","description":"Group chats are addressed by their `@g.us` JID.","value":{"phone":"120363000000000011@g.us","pin":true}},"unpin":{"summary":"Unpin a chat","description":"`pin: false` (or omitting `pin`) removes the chat from the pinned section.","value":{"phone":"5511999999999","pin":false}}}}}},"responses":{"200":{"description":"The `pin` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPinResponse"},"examples":{"pinned":{"summary":"Chat pinned","value":{"code":200,"data":{"success":true,"message":"Chat pinned successfully","jid":"5511999999999@s.whatsapp.net","pinned":true},"success":true}},"unpinned":{"summary":"Chat unpinned","value":{"code":200,"data":{"success":true,"message":"Chat unpinned successfully","jid":"5511999999999@s.whatsapp.net","pinned":false},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `phone` is missing, or `phone` is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone":{"summary":"phone missing","value":{"code":400,"error":"missing phone in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `pin` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to update pin status","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/archive":{"post":{"tags":["Chat"],"summary":"Archive or unarchive a chat","description":"Moves a chat to the **Archived** folder on every linked device, or brings it back, by sending an `archive`\napp-state mutation. The official apps may unarchive a chat again when a new message arrives, depending on the user's settings.\n\n**Rules:**\n- `phone` is required; `archive` defaults to `false`, so omitting it unarchives the chat.\n- `last_message_timestamp` (Unix seconds) and `last_message_id` describe the most recent message the archive applies to. Without a timestamp the current time is used; without `last_message_id` no message key is sent.\n- `last_message_remote_jid` overrides the chat JID inside the message key (only used together with `last_message_id`).\n- `phone` is written to the mutation as given (no LID translation).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatArchiveRequest"},"examples":{"archive":{"summary":"Archive a chat","description":"Minimal request; the archive is stamped with the current time.","value":{"phone":"5511999999999","archive":true}},"archive_with_last_message":{"summary":"Archive up to a known last message","description":"Sends the last message key so other devices anchor the archive to that message.","value":{"phone":"5511999999999","archive":true,"last_message_timestamp":1757862000,"last_message_id":"3EB0C767D26A1D6B8A9F","last_message_from_me":false}},"unarchive":{"summary":"Unarchive a group","description":"`archive: false` moves the chat back to the main list.","value":{"phone":"120363000000000011@g.us","archive":false}}}}}},"responses":{"200":{"description":"The `archive` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatArchiveResponse"},"examples":{"archived":{"summary":"Chat archived","value":{"code":200,"data":{"success":true,"message":"Chat archived successfully","jid":"5511999999999@s.whatsapp.net","archived":true},"success":true}},"unarchived":{"summary":"Chat unarchived","value":{"code":200,"data":{"success":true,"message":"Chat unarchived successfully","jid":"120363000000000011@g.us","archived":false},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `phone` is missing, or `phone` is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone":{"summary":"phone missing","value":{"code":400,"error":"missing phone in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `archive` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to update archive status","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/mute":{"post":{"tags":["Chat"],"summary":"Mute or unmute a chat","description":"Silences notifications for a chat on every linked device, or restores them, by sending a `mute` app-state mutation.\n\n**Rules:**\n- `phone` is required; `mute` defaults to `false`, so omitting it unmutes the chat.\n- `mute_duration` accepts `8h`, `1w` or `always` (case-insensitive). Omitting it while muting means `always`. Any other value returns **400**.\n- `mute_duration` is ignored when unmuting.\n- `data.duration` echoes the raw `mute_duration` sent (empty string when it was omitted) and is only present when muting.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatMuteRequest"},"examples":{"mute_8h":{"summary":"Mute for 8 hours","description":"Notifications come back automatically after 8 hours.","value":{"phone":"5511999999999","mute":true,"mute_duration":"8h"}},"mute_1w":{"summary":"Mute a group for 1 week","description":"Notifications come back automatically after 7 days.","value":{"phone":"120363000000000011@g.us","mute":true,"mute_duration":"1w"}},"mute_always":{"summary":"Mute until manually unmuted","description":"`always` keeps the chat muted with no expiry.","value":{"phone":"5511999999999","mute":true,"mute_duration":"always"}},"unmute":{"summary":"Unmute a chat","description":"Restores notifications immediately.","value":{"phone":"5511999999999","mute":false}}}}}},"responses":{"200":{"description":"The `mute` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatMuteResponse"},"examples":{"muted":{"summary":"Chat muted for 8 hours","value":{"code":200,"data":{"success":true,"message":"Chat muted successfully","jid":"5511999999999@s.whatsapp.net","muted":true,"duration":"8h"},"success":true}},"unmuted":{"summary":"Chat unmuted","value":{"code":200,"data":{"success":true,"message":"Chat unmuted successfully","jid":"5511999999999@s.whatsapp.net","muted":false},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `phone` is missing or invalid, or `mute_duration` is not one of `8h`, `1w`, `always`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone":{"summary":"phone missing","value":{"code":400,"error":"missing phone in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}},"invalid_duration":{"summary":"Unsupported mute_duration","value":{"code":400,"error":"invalid mute duration. Use: 8h, 1w, or always","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `mute` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to update mute status","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/star":{"post":{"tags":["Chat"],"summary":"Star or unstar a message","description":"Adds a message to the **Starred messages** section of every linked device, or removes it, by sending a `star`\napp-state mutation built from the message key.\n\n**Rules:**\n- `chat_jid` and `message_id` are required; `star` defaults to `false`, so omitting it unstars the message.\n- `from_me` must match the real author of the message, otherwise the mutation does not match the message on the phone.\n- For a message written by another participant in a group, send `sender_jid` with the author.\n- People are addressed by LID when the mapping is known; `index_chat_jid` shows the chat JID written to the mutation.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatStarRequest"},"examples":{"own_message_dm":{"summary":"Star a message this account sent","description":"Direct chat, message written by this account.","value":{"chat_jid":"5511999999999","message_id":"3EB0C767D26A1D6B8A9F","from_me":true,"star":true}},"group_message_from_participant":{"summary":"Star a group message from another member","description":"`sender_jid` identifies the author of the group message.","value":{"chat_jid":"120363000000000011@g.us","sender_jid":"5511888888888@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9E","from_me":false,"star":true}},"unstar":{"summary":"Unstar a received message","description":"`star: false` removes the message from Starred messages.","value":{"chat_jid":"5511999999999@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9D","from_me":false,"star":false}}}}}},"responses":{"200":{"description":"The `star` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatStarResponse"},"examples":{"starred":{"summary":"Message starred","value":{"code":200,"data":{"success":true,"message":"Message starred successfully","chat_jid":"5511999999999@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9F","starred":true,"index_chat_jid":"123456789012345@lid"},"success":true}},"unstarred":{"summary":"Message unstarred","value":{"code":200,"data":{"success":true,"message":"Message unstarred successfully","chat_jid":"5511999999999@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9D","starred":false,"index_chat_jid":"123456789012345@lid"},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `chat_jid` or `message_id` is missing, or a JID is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"chat_jid or message_id missing","value":{"code":400,"error":"missing chat_jid or message_id in payload","success":false}},"invalid_chat_jid":{"summary":"chat_jid is not a valid number or JID","value":{"code":400,"error":"invalid chat JID","success":false}},"invalid_sender_jid":{"summary":"sender_jid is not a valid number or JID","value":{"code":400,"error":"invalid sender JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `star` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to update star status","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/delete-chat":{"post":{"tags":["Chat"],"summary":"Delete a chat from the chat list","description":"Removes a whole conversation from the chat list of every linked device by sending a `deleteChat` app-state\nmutation. This is not the same as deleting a single message (`POST /chat/delete`); the chat reappears when a new message arrives.\n\n**Rules:**\n- `phone` is required and accepts a phone number, a user JID or a group JID.\n- `delete_media` defaults to `true` (media files of the chat are deleted too); send `false` to keep them.\n- `last_message_timestamp` (Unix seconds) anchors the deletion to the most recent message. `last_message_id` and `last_message_from_me` are only used together with the timestamp.\n- `last_message_sender_jid` is only used for group chats, to identify the author of the last message.\n- People are addressed by LID when this account knows the mapping (mutation index and the last message key `remoteJid`), like the official clients; groups keep their JID. The response `jid` is unchanged.\n- `last_system_message_timestamp` (optional, Unix seconds) marks the last system notice to delete, such as disappearing-messages notices. It defaults to `last_message_timestamp`, or to the current time when neither is sent.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDeleteChatRequest"},"examples":{"minimal":{"summary":"Delete a chat and its media","description":"Only `phone` is needed; media is deleted by default.","value":{"phone":"5511999999999"}},"keep_media":{"summary":"Delete a chat but keep its media","description":"`delete_media: false` keeps the media files on the devices.","value":{"phone":"5511999999999","delete_media":false}},"group_with_last_message":{"summary":"Delete a group chat up to its last message","description":"Sends the last message key, including its author, for a precise deletion.","value":{"phone":"120363000000000011@g.us","last_message_timestamp":1757862000,"last_message_id":"3EB0C767D26A1D6B8A9F","last_message_from_me":false,"last_message_sender_jid":"5511888888888@s.whatsapp.net","delete_media":true}}}}}},"responses":{"200":{"description":"The `deleteChat` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatDeleteChatResponse"},"example":{"code":200,"data":{"success":true,"message":"Chat deleted successfully","jid":"5511999999999@s.whatsapp.net","delete_media":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `phone` is missing, or `phone` is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phone":{"summary":"phone missing","value":{"code":400,"error":"missing phone in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `deleteChat` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"delete_failed":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to delete chat","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/favorite":{"post":{"tags":["Chat"],"summary":"Add or remove a chat from Favorites","description":"Adds one chat (contact or group) to the **Favorites** list of the official apps, or removes it.\n\nWhatsApp syncs Favorites as **one complete ordered list** (the `favorites` app-state action). To change a\nsingle entry the gateway applies the change on top of the list it last observed from app state or sent\nthrough this API (see `GET /chat/favorites`), then sends the whole list back.\n\n**Rules:**\n- `phone` and `favorite` are required; `phone` accepts a phone number, a user JID (`@s.whatsapp.net` / `@lid`) or a group JID (`@g.us`).\n- When the current list is unknown the request fails with **409** instead of silently wiping the other favorites.\n- `force: true` together with `favorite: true` replaces an unknown list with only this chat. `force` has no effect when removing.\n- Adding a chat that is already a favorite, or removing one that is not, still re-sends the current list.\n- People are addressed by LID when the mapping is known; `index_jid` shows the JID actually written to the sync action.\n\n**Use Cases:**\n- Mirror a CRM \"starred customer\" flag in the WhatsApp Favorites filter\n- Remove a closed conversation from Favorites\n- To set several chats at once, use `PUT /chat/favorites` with the complete list\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFavoriteRequest"},"examples":{"add_contact":{"summary":"Add a contact to Favorites","description":"Appends the contact to the end of the known Favorites list.","value":{"phone":"5511999999999","favorite":true}},"remove_contact":{"summary":"Remove a contact from Favorites","description":"Removes the contact from the known Favorites list; the remaining order is preserved.","value":{"phone":"5511999999999","favorite":false}},"force_replace_group":{"summary":"Unknown list, replace it with one group","description":"The gateway has not observed the Favorites list yet. `force` accepts replacing the whole list with only this group.","value":{"phone":"120363000000000011@g.us","favorite":true,"force":true}}}}}},"responses":{"200":{"description":"Favorites list sent to WhatsApp; `data.favorites` is the complete list after the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFavoriteResponse"},"examples":{"added":{"summary":"Contact added","value":{"code":200,"data":{"success":true,"jid":"5511999999999@s.whatsapp.net","index_jid":"123456789012345@lid","favorite":true,"favorites":["120363000000000011@g.us","123456789012345@lid"]},"success":true}},"removed":{"summary":"Contact removed","value":{"code":200,"data":{"success":true,"jid":"5511999999999@s.whatsapp.net","index_jid":"123456789012345@lid","favorite":false,"favorites":["120363000000000011@g.us"]},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, a required field is missing, or `phone` is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"phone or favorite missing","value":{"code":400,"error":"missing phone or favorite in payload","success":false}},"invalid_phone":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the gateway does not know the current Favorites list. Send the complete list with `PUT /chat/favorites`, or retry with `force: true` and `favorite: true`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":409,"error":"current favorites list is unknown to this gateway; send the complete list with PUT /chat/favorites, or force=true with favorite=true to replace it with only this chat","success":false}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the app-state update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"App-state update rejected","value":{"code":500,"error":"failed to update favorites","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/favorites":{"get":{"tags":["Chat"],"summary":"Get the Favorites list","description":"Returns the Favorites list known to the gateway for this user.\n\n**Behavior:**\n- **Without `refresh`:** returns the list last observed from app state or sent through this API. `known: false` means this process has not seen the list yet; `favorites` is then empty and does **not** mean the phone has no favorites.\n- **With `refresh=true`:** runs a full sync of the `regular_high` app-state collection and rebuilds the list from the decrypted snapshot. `complete: true` and `synced_at` are only returned after such a successful sync. The full sync does not emit favorites events to webhooks.\n\n**Rules:**\n- `source` is `app_state` (observed from the phone) or `api` (last sent through this API); it is empty while `known` is false.\n- The refresh errors (**501**, **502**, **503**) only happen with `refresh=true`. A failed sync returns **502**, never a partial list.\n- `refresh=true` is a heavy call; do not retry it automatically.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"refresh","in":"query","required":false,"description":"`true` runs a full sync of the `regular_high` app-state collection before answering. Any value that is not a boolean is treated as `false`.","schema":{"type":"boolean","default":false},"example":true}],"responses":{"200":{"description":"Favorites list as currently known by the gateway.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFavoritesListResponse"},"examples":{"refreshed":{"summary":"After refresh=true","value":{"code":200,"data":{"favorites":["123456789012345@lid","120363000000000011@g.us"],"known":true,"complete":true,"source":"app_state","synced_at":"2026-09-15T01:40:00Z"},"success":true}},"unknown":{"summary":"List not observed yet","value":{"code":200,"data":{"favorites":[],"known":false,"complete":false,"source":""},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (only with `refresh=true`): no WhatsApp session, or the session is not logged in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_logged_in":{"summary":"Session exists but is not paired","value":{"code":500,"error":"not logged in","success":false}}}}}},"501":{"description":"Not Implemented (only with `refresh=true`): the bundled WhatsApp library cannot return a full app-state snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":501,"error":"full app state snapshot is not supported by the bundled WhatsApp library","success":false}}}},"502":{"description":"Bad Gateway (only with `refresh=true`): the full sync of `regular_high` failed. No partial list is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"full sync of regular_high failed: mismatching LTHash","success":false}}}},"503":{"description":"Service Unavailable (only with `refresh=true`): the WhatsApp client is not connected.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":503,"error":"client not connected to WhatsApp","success":false}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}},"put":{"tags":["Chat"],"summary":"Replace the Favorites list","description":"Replaces the **complete ordered** Favorites list with the given chats, mirroring the official sync action,\nwhich always carries the whole list.\n\n**Rules:**\n- `phones` is required. Chats missing from the array are removed from Favorites; an empty array clears Favorites.\n- Each entry accepts a phone number, a user JID (`@s.whatsapp.net` / `@lid`) or a group JID (`@g.us`). The first invalid entry aborts the request with **400** and nothing is sent.\n- People are stored by LID when the mapping is known, so `data.favorites` may differ from the input.\n- A successful call makes the list \"known\", enabling `POST /chat/favorite` for single-chat changes.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFavoritesReplaceRequest"},"examples":{"replace_list":{"summary":"Replace Favorites with an ordered list","description":"Phone numbers, `@s.whatsapp.net`, `@lid` and group JIDs are accepted in any mix; the order is kept.","value":{"phones":["5511999999999","120363000000000011@g.us","123456789012346@lid"]}},"clear":{"summary":"Clear Favorites","description":"An empty array is valid and removes every favorite. Omitting `phones` returns 400.","value":{"phones":[]}}}}}},"responses":{"200":{"description":"Favorites list sent to WhatsApp; `data.favorites` is the list exactly as written to the sync action.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatFavoritesReplaceResponse"},"example":{"code":200,"data":{"success":true,"favorites":["123456789012345@lid","120363000000000011@g.us","123456789012346@lid"]},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `phones` is missing, or an entry is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_phones":{"summary":"phones missing","value":{"code":400,"error":"missing phones in payload","success":false}},"invalid_entry":{"summary":"An entry is not a valid number or JID","value":{"code":400,"error":"invalid phone number: @s.whatsapp.net","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the app-state update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"App-state update rejected","value":{"code":500,"error":"failed to update favorites","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/pin-message":{"post":{"tags":["Chat"],"summary":"Pin or unpin a message inside a chat","description":"Sends the official `PinInChatMessage` (`PIN_FOR_ALL` / `UNPIN_FOR_ALL`) that shows the pinned-message banner at the\ntop of the conversation for every participant. To pin the chat itself in the chat list use `POST /chat/pin`.\n\n**Rules:**\n- `phone`, `message_id`, `from_me` and `pin` are all required (`false` counts as present).\n- `duration_seconds` accepts `86400` (24 hours), `604800` (7 days, default) or `2592000` (30 days); any other value returns **400**. It is ignored when unpinning.\n- `from_me` tells whether the target message was sent by this account.\n- In a group, pinning another participant's message requires `sender_jid` (**400** otherwise). For your own message in a group the gateway fills in this account as the author.\n- People are addressed by LID when the mapping is known, so the embedded key matches the destination.\n- WhatsApp may restrict pinning to group admins depending on the group settings.\n- This sends a protocol message: do not retry automatically after an uncertain failure.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPinMessageRequest"},"examples":{"pin_7_days":{"summary":"Pin for 7 days (default)","description":"No `duration_seconds`, so the default 7-day pin is used.","value":{"phone":"5511999999999","message_id":"3EB0C767D26A1D6B8A9F","from_me":true,"pin":true}},"pin_group_24h":{"summary":"Pin another member's group message for 24 hours","description":"`sender_jid` is required because the message was written by another participant.","value":{"phone":"120363000000000011@g.us","message_id":"3EB0C767D26A1D6B8A9E","from_me":false,"sender_jid":"5511888888888@s.whatsapp.net","pin":true,"duration_seconds":86400}},"pin_contact_message":{"summary":"Pin a message received in a 1:1 chat","description":"In a private chat the author of a message you did not send is the contact itself, so `from_me: false` needs no `sender_jid`.","value":{"phone":"5511999999999","message_id":"3EB0C767D26A1D6B8A9D","from_me":false,"pin":true}},"unpin":{"summary":"Unpin a message","description":"`pin: false` removes the pinned-message banner; `duration_seconds` is ignored.","value":{"phone":"5511999999999","message_id":"3EB0C767D26A1D6B8A9F","from_me":true,"pin":false}}}}}},"responses":{"200":{"description":"The pin message was sent and acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPinMessageResponse"},"examples":{"pinned":{"summary":"Message pinned for 7 days","value":{"code":200,"data":{"success":true,"id":"3EB0B1C2D3E4F5A6B7C8","chat":"123456789012345@lid","message_id":"3EB0C767D26A1D6B8A9F","pinned":true,"timestamp":1757862000,"duration_seconds":604800},"success":true}},"unpinned":{"summary":"Message unpinned","value":{"code":200,"data":{"success":true,"id":"3EB0B1C2D3E4F5A6B7C9","chat":"123456789012345@lid","message_id":"3EB0C767D26A1D6B8A9F","pinned":false,"timestamp":1757862060},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, a required field is missing, a JID is invalid, `duration_seconds` is not allowed, or `sender_jid` is missing for another member's group message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"Required field missing","value":{"code":400,"error":"missing phone, message_id, from_me or pin in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}},"invalid_duration":{"summary":"Unsupported duration_seconds","value":{"code":400,"error":"invalid duration_seconds: must be 86400, 604800 or 2592000","success":false}},"sender_required":{"summary":"Group message from another member without sender_jid","value":{"code":400,"error":"sender_jid is required for another participant's message in a group","success":false}},"invalid_sender_jid":{"summary":"sender_jid is not a valid number or JID","value":{"code":400,"error":"invalid sender JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the pin message could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send pin message","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/list":{"get":{"tags":["Sync"],"summary":"List chats with pinned, archived and muted settings","description":"Lists the chats whose settings (pinned, archived, muted) were already synchronized into the local database table `whatsmeow_chat_settings`. The call reads the database only; it does not contact WhatsApp.\n\n**Rules:**\n- Only chats that have at least one setting stored are returned, ordered pinned first, then non-archived. Read/unread state and names are not stored and are not returned.\n- `phone_number` is the user part of the JID (for `@lid` and `@g.us` chats it is the LID or group ID, not a phone number).\n- Run `POST /sync/app-state` first when the list looks incomplete.\n- When no WhatsApp client exists for this user the response is **404** in the legacy envelope: the message sits in `data` and `success` stays `true`, so check the HTTP status.\n- A session that was never paired returns **500** `not logged in`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Chats with stored settings and summary counters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncChatListResponse"},"example":{"code":200,"data":{"success":true,"chats":[{"chat_jid":"5511999999999@s.whatsapp.net","phone_number":"5511999999999","pinned":true,"archived":false},{"chat_jid":"120363000000000011@g.us","phone_number":"120363000000000011","muted_until":1767225600,"pinned":false,"archived":true}],"stats":{"total":2,"pinned_count":1,"archived_count":1,"muted_count":1}},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found (legacy envelope): no WhatsApp client exists for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":404,"data":"Client not found","success":true}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the session was never paired (standard envelope), or the database query failed (legacy envelope).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"not_logged_in":{"summary":"Session not paired","value":{"code":500,"error":"not logged in","success":false}},"database_query_failed":{"summary":"Database query failed (legacy envelope)","value":{"code":500,"data":"Database query failed: pq: relation \"whatsmeow_chat_settings\" does not exist","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/sync/app-state":{"post":{"tags":["Sync"],"summary":"Resynchronize all app-state collections","description":"Fetches the five app-state collections (`critical_block`, `critical_unblock_low`, `regular_low`, `regular_high`, `regular`) from WhatsApp without reconnecting, updating chat settings, contacts, labels and other synced data in the local store.\n\n**Behavior:**\n- The collections are fetched one after another; the call always answers **200** once all five were attempted. `data.success` is `false` when any collection failed, and each item in `data.results` carries its own `success`, `error` and `duration`.\n- With `auto_recovery` (default `true`) a failed collection triggers an app-state recovery request to the primary phone; `recovery_requested` shows whether it was sent. Requests are limited to one per collection every 2 minutes (`recovery_skipped: true` otherwise), because the phone stops answering repeated requests. Recovered data arrives later through app-state events.\n\n**Rules:**\n- Options come from a JSON body when one is sent; a body that does not parse is ignored and the defaults (`full_sync: true`, `auto_recovery: true`) are kept.\n- Without a body, the `full_sync` and `auto_recovery` query or form parameters are read; only the literal value `false` disables an option.\n- `full_sync: true` discards the local collection versions and downloads full snapshots; `false` only fetches patches newer than the stored versions.\n- Precondition failures use the legacy envelope (message in `data`, `success: true`): **404** when no client exists and **400** when it is not connected. A never-paired session returns **500** `not logged in`.\n- Full syncs can take several seconds; do not call this in a tight loop.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"full_sync","in":"query","required":false,"description":"Only read when the request has no body. `false` fetches incremental patches instead of full snapshots.","schema":{"type":"boolean","default":true},"example":false},{"name":"auto_recovery","in":"query","required":false,"description":"Only read when the request has no body. `false` disables the recovery request for failed collections.","schema":{"type":"boolean","default":true},"example":true}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncAppStateRequest"},"examples":{"defaults":{"summary":"Full resync with automatic recovery","description":"Same as sending no body at all.","value":{"full_sync":true,"auto_recovery":true}},"incremental_no_recovery":{"summary":"Incremental fetch without recovery","description":"Fetches only newer patches and never asks the phone for a recovery snapshot.","value":{"full_sync":false,"auto_recovery":false}}}}}},"responses":{"200":{"description":"All five collections were attempted; inspect `data.success` and `data.results`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncAppStateResponse"},"examples":{"all_synced":{"summary":"Every collection synchronized","value":{"code":200,"data":{"success":true,"message":"App state synchronized successfully. All 5 patch types updated.","auto_recovery_enabled":true,"results":[{"name":"critical_block","success":true,"duration":"812.4ms"},{"name":"critical_unblock_low","success":true,"duration":"640.1ms"},{"name":"regular_low","success":true,"duration":"1.203s"},{"name":"regular_high","success":true,"duration":"955.7ms"},{"name":"regular","success":true,"duration":"1.412s"}]},"success":true}},"partial_failure":{"summary":"One collection failed and recovery was requested","value":{"code":200,"data":{"success":false,"message":"App state sync completed with errors. Recovery requested for 1 failed patches. Check results for details.","auto_recovery_enabled":true,"results":[{"name":"critical_block","success":true,"duration":"790.2ms"},{"name":"critical_unblock_low","success":true,"duration":"610.8ms"},{"name":"regular_low","success":true,"duration":"1.101s"},{"name":"regular_high","success":false,"error":"failed to verify patch v1234: mismatching LTHash","duration":"2.034s","recovery_requested":true},{"name":"regular","success":true,"duration":"1.388s"}]},"success":true}}}}}},"400":{"description":"Bad Request (legacy envelope): the WhatsApp client is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":400,"data":"Client not connected to WhatsApp","success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found (legacy envelope): no WhatsApp client exists for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":404,"data":"Client not found","success":true}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the session was never paired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"not logged in","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/sync/history-request":{"post":{"tags":["Sync"],"summary":"Request older messages of one chat from the phone","description":"Asks the primary phone for messages of one chat that are older than a known message (on-demand history sync). The messages are **not** returned in the HTTP response; they arrive asynchronously as `HistorySync` events through the webhook, WebSocket and other transports.\n\n**Rules:**\n- `phone`, `oldest_message_id` and `oldest_message_timestamp` are required. `phone` accepts a phone number, a user JID or a group JID.\n- `oldest_message_timestamp` is the timestamp of that oldest known message in **milliseconds** since the Unix epoch.\n- `oldest_from_me` must match the author of that message. `count` defaults to 50; WhatsApp decides how many messages are really sent.\n- `data.request_id` is simply the `oldest_message_id`; the phone must be online for history to arrive.\n- Every validation and precondition failure uses the legacy envelope: the text is in `data` and `success` is `true`. Branch on the HTTP status (**400**, **404**, **500**).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHistoryRequestRequest"},"examples":{"default_count":{"summary":"Request the default 50 older messages","description":"`count` omitted, so 50 messages are requested.","value":{"phone":"5511999999999","oldest_message_id":"3EB0C767D26A1D6B8A9F","oldest_message_timestamp":1757862000000,"oldest_from_me":false}},"group_page":{"summary":"Page 100 older messages of a group","description":"Uses the oldest message already stored as the anchor for the next page.","value":{"phone":"120363000000000011@g.us","oldest_message_id":"3EB0C767D26A1D6B8A9E","oldest_message_timestamp":1757775600000,"oldest_from_me":true,"count":100}}}}}},"responses":{"200":{"description":"The history request was sent to the primary phone; results arrive later as `HistorySync` events.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncHistoryRequestResponse"},"example":{"code":200,"data":{"success":true,"message":"History sync request sent successfully. History will arrive asynchronously via HistorySync events (webhook/websocket).","request_id":"3EB0C767D26A1D6B8A9F","chat":"5511999999999@s.whatsapp.net","count":50},"success":true}}}},"400":{"description":"Bad Request (legacy envelope): client not connected, body not valid JSON, a required field missing, or `phone` invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"examples":{"client_not_connected":{"summary":"Client not connected","value":{"code":400,"data":"Client not connected to WhatsApp","success":true}},"invalid_request_body":{"summary":"Body is not valid JSON","value":{"code":400,"data":"Invalid request body","success":true}},"phone_is_required":{"summary":"phone missing","value":{"code":400,"data":"phone is required","success":true}},"oldest_message_id_is_required":{"summary":"oldest_message_id missing","value":{"code":400,"data":"oldest_message_id is required","success":true}},"oldest_message_timestamp_is_required":{"summary":"oldest_message_timestamp missing or zero","value":{"code":400,"data":"oldest_message_timestamp is required","success":true}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"data":"Invalid phone number","success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found (legacy envelope): no WhatsApp client exists for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":404,"data":"Client not found","success":true}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (legacy envelope): the request could not be sent to the phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":500,"data":"Failed to send history sync request: websocket not connected","success":true}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/sync/full-history":{"post":{"tags":["Sync"],"summary":"Request a full history sync from the phone","description":"Asks the primary phone to resend the chat history of all chats (full history sync on demand), like the initial sync after pairing. The history arrives asynchronously as `HistorySync` events; the HTTP response only confirms the request.\n\n**Rules:**\n- The body is optional and any decode error is ignored. Defaults: `days_limit` 30, `size_mb_limit` 1000, `include_groups` true, `include_calls` false. `days_limit` or `size_mb_limit` sent as `0` also fall back to the defaults.\n- `size_mb_limit` is used both as the full-sync size limit and as the storage quota announced to the phone.\n- `data.request_id` is a random 32-character hexadecimal ID and `data.config` echoes the effective limits.\n- Large histories can take minutes and generate many webhook events; the phone must stay online.\n- A disconnected client (**400**), a missing client (**404**) and a failed send (**500**) answer with the legacy envelope, where `data` is the message and `success` remains `true`. A never-paired session returns **500** `not logged in` in the standard envelope.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncFullHistoryRequest"},"examples":{"defaults":{"summary":"Last 30 days including groups","description":"Same as sending no body.","value":{"days_limit":30,"size_mb_limit":1000,"include_groups":true,"include_calls":false}},"one_year_with_calls":{"summary":"One year of history with call logs","description":"Larger window and size limit, also asking for the call log history.","value":{"days_limit":365,"size_mb_limit":5000,"include_groups":true,"include_calls":true}}}}}},"responses":{"200":{"description":"The full history request was sent to the primary phone.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncFullHistoryResponse"},"example":{"code":200,"data":{"success":true,"message":"Full history sync requested successfully. History will arrive asynchronously via HistorySync events (webhook/websocket). This works exactly like the initial connection sync.","request_id":"9F3A6C1E2B7D4058A1C3E5F7092B4D6E","config":{"days_limit":30,"size_mb_limit":1000,"include_groups":true,"include_calls":false}},"success":true}}}},"400":{"description":"Bad Request (legacy envelope): the WhatsApp client is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":400,"data":"Client not connected to WhatsApp","success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found (legacy envelope): no WhatsApp client exists for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":404,"data":"Client not found","success":true}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the session was never paired (standard envelope), or the request could not be sent (legacy envelope).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"not_logged_in":{"summary":"Session not paired","value":{"code":500,"error":"not logged in","success":false}},"send_failed":{"summary":"Request could not be sent (legacy envelope)","value":{"code":500,"data":"Failed to send full history sync request: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/label/manage":{"post":{"tags":["Label"],"summary":"Create, edit or delete a label","description":"Creates, edits or deletes a label (called a \"list\" in the personal WhatsApp app) by sending a `label_edit`\napp-state mutation. Labels are then applied to chats with `POST /label/chat`.\n\n**Operations:**\n- **Create:** omit `label_id` and send `label_name` (and optionally `label_color`). The gateway generates a free numeric ID and creates an active `CUSTOM` list; the response carries `label_id_generated: true` and `label_type: \"CUSTOM\"`.\n- **Edit:** send an existing `label_id` with the new `label_name` and `label_color`. If the label was observed from app state, its official fields (type, order, predefined ID) are preserved and `label_type` is returned.\n- **Delete:** send `label_id` with `delete: true`; `label_name` and `label_color` are ignored.\n\n**Rules:**\n- Official clients only display labels with numeric IDs. Generated IDs are the highest known numeric ID + 1 once labels were observed from app state, otherwise the current Unix time in seconds.\n- `label_name` is required unless `delete` is `true`; `label_id` is required when `delete` is `true`.\n- `label_color` is the palette index and is not range-checked by the gateway. When omitted it is sent as `0`.\n- The response `message` reads `Label updated successfully` for both create and edit (only delete reads `Label deleted successfully`); use `label_id_generated` to recognize a new label.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelManageRequest"},"examples":{"create_generated_id":{"summary":"Create a label with a generated ID","description":"No `label_id`, so the gateway picks a free numeric ID and creates an active CUSTOM list.","value":{"label_name":"Hot leads","label_color":3}},"update_existing":{"summary":"Rename and recolor label 12","description":"Edits an existing label; official fields observed from app state are kept.","value":{"label_id":"12","label_name":"Follow-up","label_color":5}},"delete":{"summary":"Delete label 12","description":"Only `label_id` and `delete` are needed to delete a label.","value":{"label_id":"12","delete":true}}}}}},"responses":{"200":{"description":"The `label_edit` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelManageResponse"},"examples":{"created_generated":{"summary":"Created without label_id","value":{"code":200,"data":{"success":true,"message":"Label updated successfully","label_id":"13","label_id_generated":true,"label_type":"CUSTOM","label_name":"Hot leads","label_color":3},"success":true}},"updated_explicit_id":{"summary":"Edited a label not observed from app state","value":{"code":200,"data":{"success":true,"message":"Label updated successfully","label_id":"12","label_id_generated":false,"label_name":"Follow-up","label_color":5},"success":true}},"deleted":{"summary":"Deleted","value":{"code":200,"data":{"success":true,"message":"Label deleted successfully","label_id":"12","label_id_generated":false},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `label_name` is missing on create/edit, or `label_id` is missing on delete.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"label_id_required_for_deletion":{"summary":"Delete without label_id","value":{"code":400,"error":"label_id required for deletion","success":false}},"label_name_required":{"summary":"Create or edit without label_name","value":{"code":400,"error":"label_name required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `label_edit` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"failed_to_manage_label":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to manage label","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/label/chat":{"post":{"tags":["Label"],"summary":"Apply or remove a label on a chat","description":"Applies a label to a chat (contact or group), or removes it, by sending a `label_jid` app-state mutation.\nThis is the label association the official apps display in the chat list filters.\n\n**Rules:**\n- `phone` and `label_id` are required; `apply` defaults to `false`, so omitting it removes the label.\n- `phone` accepts a phone number, a user JID (`@s.whatsapp.net` / `@lid`) or a group JID (`@g.us`).\n- People are addressed by LID when the mapping is known; groups keep their JID. `index_jid` shows the JID written to the mutation.\n- The gateway does not check that `label_id` exists; use `GET /label/list` to find valid IDs.\n- A chat can carry several labels; each call changes only the given label.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelChatRequest"},"examples":{"apply_to_contact":{"summary":"Apply label 12 to a contact","description":"The contact is addressed by LID in the mutation when the mapping is known.","value":{"phone":"5511999999999","label_id":"12","apply":true}},"remove_from_group":{"summary":"Remove label 12 from a group","description":"Group chats keep their `@g.us` JID in the mutation index.","value":{"phone":"120363000000000011@g.us","label_id":"12","apply":false}}}}}},"responses":{"200":{"description":"The `label_jid` mutation was accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelChatResponse"},"examples":{"applied":{"summary":"Label applied to a contact","value":{"code":200,"data":{"success":true,"message":"Label applied successfully","jid":"5511999999999@s.whatsapp.net","label_id":"12","applied":true,"index_jid":"123456789012345@lid"},"success":true}},"removed":{"summary":"Label removed from a group","value":{"code":200,"data":{"success":true,"message":"Label removed successfully","jid":"120363000000000011@g.us","label_id":"12","applied":false,"index_jid":"120363000000000011@g.us"},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `phone` or `label_id` is missing, or `phone` is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"phone or label_id missing","value":{"code":400,"error":"missing phone or label_id in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `label_jid` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"failed_to_update_label_status":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to update label status","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/label/message":{"post":{"tags":["Label"],"summary":"Apply or remove a label on a message","description":"Applies a label to a single message, or removes it, by sending a `label_message` app-state mutation.\n\n**Rules:**\n- Kept for compatibility only: the official WhatsApp apps do **not** display message labels (`label_message` is not an action of the official sync engine), so a 200 does not make a label visible on the phone. Use `POST /label/chat` to label conversations.\n- `phone`, `message_id` and `label_id` are required; `apply` defaults to `false`, so omitting it removes the label.\n- `phone` is the chat that holds the message (phone number, user JID or group JID). It is used as given; no LID translation is applied.\n- The gateway does not check that the message or the label exists.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelMessageRequest"},"examples":{"apply":{"summary":"Apply label 12 to a message","description":"Labels message 3EB0C767D26A1D6B8A9F in a direct chat.","value":{"phone":"5511999999999","message_id":"3EB0C767D26A1D6B8A9F","label_id":"12","apply":true}},"remove":{"summary":"Remove label 12 from a group message","description":"Removes the label from a message inside a group chat.","value":{"phone":"120363000000000011@g.us","message_id":"3EB0C767D26A1D6B8A9F","label_id":"12","apply":false}}}}}},"responses":{"200":{"description":"The `label_message` mutation was accepted by WhatsApp (not displayed by the official apps).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelMessageResponse"},"example":{"code":200,"data":{"success":true,"message":"Label applied successfully","jid":"5511999999999@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9F","label_id":"12","applied":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, a required field is missing, or `phone` is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"phone, message_id or label_id missing","value":{"code":400,"error":"missing phone, message_id or label_id in payload","success":false}},"invalid_phone_number":{"summary":"phone is not a valid number or JID","value":{"code":400,"error":"invalid phone number","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or WhatsApp rejected the `label_message` mutation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"failed_to_update_label_status":{"summary":"Mutation rejected","value":{"code":500,"error":"failed to update label status","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/label/list":{"get":{"tags":["Label"],"summary":"List labels and their chats","description":"Lists the labels (called \"lists\" in the personal WhatsApp app) known to the gateway, with the chats that carry each one.\n\n**Behavior:**\n- **Without `refresh`:** returns only what this gateway process observed from app-state events or created/edited through the API. `complete` is `false`.\n- **With `refresh=true`:** runs a full sync of the `regular` app-state collection and rebuilds the list from the decrypted snapshot, including system lists (`UNREAD`, `FAVORITES`, `GROUPS`), `PREDEFINED` Business labels and `CUSTOM` lists. `complete: true` and `synced_at` are only returned after that sync succeeds.\n\n**Rules:**\n- Deleted labels are included with `deleted: true`.\n- Labels created by older gateway versions with a non-numeric ID (`label_<unix>`) are listed but not shown by the official apps.\n- The full sync does not emit label events to webhooks, and message labels (`POST /label/message`) are never part of this list.\n- The refresh errors (**500**, **501**, **502**, **503**) only happen with `refresh=true`. `refresh=true` is a heavy call; do not retry it automatically.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"refresh","in":"query","required":false,"description":"`true` runs a full sync of the `regular` app-state collection before answering. Any value that is not a boolean is treated as `false`.","schema":{"type":"boolean","default":false},"example":true}],"responses":{"200":{"description":"Labels known to the gateway, sorted by order index.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelListResponse"},"examples":{"refreshed":{"summary":"After refresh=true","value":{"code":200,"data":{"labels":[{"id":"11","name":"Unread","color":0,"deleted":false,"predefined_id":0,"order_index":-12,"is_active":true,"type":"UNREAD","is_immutable":false,"source":"app_state","updated_at":"2026-07-02T15:19:25-03:00","chats":[]},{"id":"16","name":"New customer","color":1,"deleted":false,"predefined_id":1,"order_index":10,"is_active":true,"type":"PREDEFINED","is_immutable":false,"source":"app_state","updated_at":"2026-07-02T15:19:25-03:00","chats":["123456789012345@lid"]},{"id":"1757862000","name":"VIP","color":3,"deleted":false,"order_index":1757862000,"is_active":true,"type":"CUSTOM","is_immutable":false,"source":"api","updated_at":"2026-09-14T10:05:00Z","chats":["120363000000000011@g.us"]}],"complete":true,"observed_from_app_state":true,"synced_at":"2026-09-15T01:39:35Z","note":"message labels (label_message) are not shown by the official apps"},"success":true}},"observed_only":{"summary":"Without refresh, nothing observed yet","value":{"code":200,"data":{"labels":[],"complete":false,"observed_from_app_state":false,"note":"message labels (label_message) are not shown by the official apps"},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error (only with `refresh=true`): no WhatsApp session, or the session is not logged in.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_logged_in":{"summary":"Session exists but is not paired","value":{"code":500,"error":"not logged in","success":false}}}}}},"501":{"description":"Not Implemented (only with `refresh=true`): the bundled WhatsApp library cannot return a full app-state snapshot.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":501,"error":"full app state snapshot is not supported by the bundled WhatsApp library","success":false}}}},"502":{"description":"Bad Gateway (only with `refresh=true`): the full sync of `regular` failed. No partial list is returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"full sync of regular failed: mismatching LTHash","success":false}}}},"503":{"description":"Service Unavailable (only with `refresh=true`): the WhatsApp client is not connected.\n\n**Pela API pública:** Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":503,"error":"client not connected to WhatsApp","success":false}},"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}},"headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}}}}}},"/group/create":{"post":{"tags":["Group"],"summary":"Create a group","description":"Creates a WhatsApp group with the session as creator and super admin, adds the initial participants and returns\nthe new group's full `GroupInfo`.\n\n**Rules:**\n- `Name` is required and must not be empty; `Participants` must contain at least one phone number or user JID.\n- One unparsable participant aborts the request with **400** before anything is created.\n- WhatsApp may refuse individual participants (privacy settings, not on WhatsApp). The group is still created: those entries come back in `Participants` with a non-zero `Error` and, when an invite is required, an `AddRequest` code.\n- The response is the raw `GroupInfo`; use `JID` for every later group call.\n\n**Use Cases:**\n- Open a dedicated group per customer, order or project\n- Create an internal team group from a CRM action\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGroup"},"examples":{"phones":{"summary":"Participants as phone numbers","description":"Numbers include the country code, without `+` or separators.","value":{"Name":"Project Team","Participants":["5511999999999","5511988888888"]}},"jids":{"summary":"Participants as user JIDs","description":"Phone JIDs and LIDs are accepted; keys are matched case-insensitively.","value":{"name":"Project Team","participants":["5511999999999@s.whatsapp.net","123456789012345@lid"]}}}}}},"responses":{"200":{"description":"Group created; `data` is the new group's `GroupInfo`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupInfoResponse"},"example":{"code":200,"data":{"JID":"120363000000000011@g.us","OwnerJID":"123456789012340@lid","OwnerPN":"5511977777777@s.whatsapp.net","Name":"Project Team","NameSetAt":"2026-09-15T12:00:00Z","NameSetBy":"123456789012340@lid","NameSetByPN":"5511977777777@s.whatsapp.net","Topic":"","TopicID":"","TopicSetAt":"0001-01-01T00:00:00Z","TopicSetBy":"","TopicSetByPN":"","TopicDeleted":false,"IsLocked":false,"IsAnnounce":false,"AnnounceVersionID":"","IsEphemeral":false,"DisappearingTimer":0,"IsIncognito":false,"IsParent":false,"DefaultMembershipApprovalMode":"","LinkedParentJID":"","IsDefaultSubGroup":false,"IsJoinApprovalRequired":false,"AddressingMode":"lid","GroupCreated":"2026-09-15T12:00:00Z","CreatorCountryCode":"BR","ParticipantVersionID":"","Participants":[{"JID":"123456789012340@lid","PhoneNumber":"5511977777777@s.whatsapp.net","LID":"123456789012340@lid","Username":"","IsAdmin":true,"IsSuperAdmin":true,"DisplayName":"","Error":0,"AddRequest":null},{"JID":"123456789012345@lid","PhoneNumber":"5511999999999@s.whatsapp.net","LID":"123456789012345@lid","Username":"","IsAdmin":false,"IsSuperAdmin":false,"DisplayName":"","Error":0,"AddRequest":null},{"JID":"5511988888888@s.whatsapp.net","PhoneNumber":"5511988888888@s.whatsapp.net","LID":"","Username":"","IsAdmin":false,"IsSuperAdmin":false,"DisplayName":"","Error":403,"AddRequest":{"Code":"AbCdEfGhIjKlMnOp","Expiration":"2026-09-18T12:00:00Z"}}],"ParticipantCount":3,"MemberAddMode":"admin_add","Suspended":false},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, missing `Name` or `Participants`, or an unparsable participant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_name":{"summary":"Name missing or empty","value":{"code":400,"error":"missing Name in Payload","success":false}},"missing_participants":{"summary":"Participants missing or empty","value":{"code":400,"error":"missing Participants in Payload","success":false}},"invalid_participant":{"summary":"A participant is not a valid number or JID","value":{"code":400,"error":"could not parse Participant Phone","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the creation (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Client disconnected (legacy envelope)","value":{"code":500,"data":"failed to create group: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/locked":{"post":{"tags":["Group"],"summary":"Lock or unlock editing of group info","description":"Controls the **Edit group settings** permission: when locked, only admins can change the group name, photo, description\nand disappearing-messages timer; when unlocked, every member can. The session must be an admin of the group.\n\n**Rules:**\n- `groupjid` is required and should be a group JID (`@g.us`).\n- `locked` defaults to `false` when omitted, which **unlocks** the group.\n- The response only confirms that WhatsApp accepted the change; use `GET /group/info` (`IsLocked`) to read the current state.\n\n**Use Cases:**\n- Keep a customer group's name and photo under admin control\n- Let project members update the group description themselves\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupLocked"},"examples":{"lock":{"summary":"Only admins can edit group info","description":"Locks the name, photo and description to admins.","value":{"groupjid":"120363000000000011@g.us","locked":true}},"unlock":{"summary":"Every member can edit group info","description":"Removes the admin-only restriction.","value":{"groupjid":"120363000000000011@g.us","locked":false}}}}}},"responses":{"200":{"description":"WhatsApp accepted the new locked setting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group Locked setting updated successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `groupjid` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"groupjid is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the change (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Session is not an admin (legacy envelope)","value":{"code":500,"data":"failed to set group locked: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/ephemeral":{"post":{"tags":["Group"],"summary":"Set the disappearing messages timer of a group","description":"Turns disappearing messages on or off for a group. New messages sent after the change disappear once the chosen\nduration has passed; existing messages are not affected.\n\n**Rules:**\n- `groupjid` and `duration` are required.\n- `duration` accepts exactly `24h`, `7d`, `90d` or `off`. Any other value returns **400**.\n- When the group is locked (`POST /group/locked`), only admins can change the timer.\n\n**Use Cases:**\n- Keep short-lived coordination groups clean after 24 hours\n- Disable disappearing messages in a group used as an audit trail\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupEphemeral"},"examples":{"seven_days":{"summary":"Messages disappear after 7 days","description":"Enables disappearing messages with the 7-day timer.","value":{"groupjid":"120363000000000011@g.us","duration":"7d"}},"one_day":{"summary":"Messages disappear after 24 hours","description":"Enables disappearing messages with the 24-hour timer.","value":{"groupjid":"120363000000000011@g.us","duration":"24h"}},"off":{"summary":"Turn disappearing messages off","description":"New messages are kept until deleted.","value":{"groupjid":"120363000000000011@g.us","duration":"off"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the new timer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Disappearing timer set successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, unparsable `groupjid`, missing `duration`, or a `duration` outside the accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"groupjid is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}},"missing_duration":{"summary":"duration missing","value":{"code":400,"error":"missing Duration in Payload","success":false}},"invalid_duration":{"summary":"duration not accepted","value":{"code":400,"error":"invalid duration. Use: 24h, 7d, 90d, or off","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the change (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Client disconnected (legacy envelope)","value":{"code":500,"data":"failed to set disappearing timer: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/photo/remove":{"post":{"tags":["Group"],"summary":"Remove the group photo","description":"Deletes the current profile photo of a group, leaving the default group avatar.\n\n**Rules:**\n- `groupjid` is required and should be a group JID (`@g.us`).\n- When the group is locked (`POST /group/locked`), only admins can remove the photo.\n- Removing a photo from a group that has none is decided by WhatsApp; an error comes back as **500** in the legacy envelope.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveGroupPhoto"},"examples":{"remove":{"summary":"Remove the photo of a group","description":"Only the group JID is needed.","value":{"groupjid":"120363000000000011@g.us"}}}}}},"responses":{"200":{"description":"Photo removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group Photo removed successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `groupjid` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"groupjid is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the removal (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Not allowed to change the photo (legacy envelope)","value":{"code":500,"data":"failed to remove group photo: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/list":{"get":{"tags":["Group"],"summary":"List joined groups","description":"Returns every group the session currently participates in, fetched live from WhatsApp, each as a full `GroupInfo`.\n\n**Rules:**\n- `ignoreParticipants=true` drops the `Participants` array from every group (`ParticipantCount` is kept). Only the exact string `true` enables it.\n- Use `IsParent` and `LinkedParentJID` to tell communities and community-linked groups apart from regular groups.\n- When the session is in no group, `Groups` is `null`.\n\n**Use Cases:**\n- Sync the group directory into a CRM\n- Find a group JID by name before calling other group routes\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"ignoreParticipants","in":"query","required":false,"description":"`true` removes the participant list from every group to reduce the response size. Any other value keeps it.","schema":{"type":"boolean","default":false},"example":true}],"responses":{"200":{"description":"Joined groups.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupListResponse"},"examples":{"without_participants":{"summary":"With ignoreParticipants=true","value":{"code":200,"data":{"Groups":[{"JID":"120363000000000011@g.us","OwnerJID":"123456789012340@lid","OwnerPN":"5511977777777@s.whatsapp.net","Name":"Project Team","NameSetAt":"2026-09-15T12:00:00Z","NameSetBy":"123456789012340@lid","NameSetByPN":"5511977777777@s.whatsapp.net","Topic":"Weekly status and deadlines","TopicID":"1757937600000000","TopicSetAt":"2026-09-15T12:05:00Z","TopicSetBy":"123456789012340@lid","TopicSetByPN":"5511977777777@s.whatsapp.net","TopicDeleted":false,"IsLocked":true,"IsAnnounce":false,"AnnounceVersionID":"1757937600000000","IsEphemeral":false,"DisappearingTimer":0,"IsIncognito":false,"IsParent":false,"DefaultMembershipApprovalMode":"","LinkedParentJID":"","IsDefaultSubGroup":false,"IsJoinApprovalRequired":false,"AddressingMode":"lid","GroupCreated":"2026-09-15T12:00:00Z","CreatorCountryCode":"BR","ParticipantVersionID":"1757937600000001","Participants":null,"ParticipantCount":12,"MemberAddMode":"admin_add","Suspended":false}]},"success":true}},"no_groups":{"summary":"Session is in no group","value":{"code":200,"data":{"Groups":null},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or the WhatsApp query failed (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"Client disconnected (legacy envelope)","value":{"code":500,"data":"failed to get group list: websocket not connected","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/invitelink":{"get":{"tags":["Group"],"summary":"Get or reset the group invite link","description":"Returns the `https://chat.whatsapp.com/...` invite link of a group. With `reset=true` WhatsApp revokes the current\nlink and issues a new one. Only admins can read or reset the link.\n\n**Rules:**\n- `groupJID` is required. `reset` accepts any value Go parses as a boolean (`true`, `false`, `1`, `0`, `t`, `f`); anything else returns **400**.\n- Resetting invalidates every previously shared link immediately.\n- Not being an admin, not being a member, or an unknown group returns **500** in the legacy envelope with the WhatsApp reason.\n\n**Use Cases:**\n- Share the join link in an email or landing page\n- Rotate a leaked invite link\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"groupJID","in":"query","required":true,"description":"Group JID (`@g.us`).","schema":{"type":"string"},"example":"120363000000000011@g.us"},{"name":"reset","in":"query","required":false,"description":"`true` revokes the current link and returns a new one.","schema":{"type":"boolean","default":false},"example":false}],"responses":{"200":{"description":"Current (or newly generated) invite link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupInviteLinkResponse"},"example":{"code":200,"data":{"InviteLink":"https://chat.whatsapp.com/AbCdEfGhIjKlMnOpQrStUv"},"success":true}}}},"400":{"description":"Bad Request: missing `groupJID`, invalid `reset`, or unparsable `groupJID`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_group_jid":{"summary":"groupJID missing","value":{"code":400,"error":"missing groupJID parameter","success":false}},"invalid_reset":{"summary":"reset is not a boolean","value":{"code":400,"error":"invalid reset parameter, must be true or false","success":false}},"could_not_parse_group_jid":{"summary":"groupJID is invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp refused the request (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_admin":{"summary":"Session is not an admin (legacy envelope)","value":{"code":500,"data":"Failed to get group invite link: you don't have the permission to get the group's invite link","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/info":{"get":{"tags":["Group"],"summary":"Get group information","description":"Returns the full `GroupInfo` of one group, fetched live from WhatsApp: name, description, settings, community links\nand the participant list with admin flags.\n\n**Rules:**\n- `groupJID` is required and must be a group the session belongs to.\n- People are identified by LID in groups using `AddressingMode: lid`; `PhoneNumber` carries the phone JID when WhatsApp shares it.\n- Not a member, or an unknown group, returns **500** in the legacy envelope with the WhatsApp reason.\n\n**Use Cases:**\n- Check whether the session is an admin before changing settings\n- Read the participant list to sync members into another system\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"groupJID","in":"query","required":true,"description":"Group JID (`@g.us`).","schema":{"type":"string"},"example":"120363000000000011@g.us"}],"responses":{"200":{"description":"Group information.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupInfoResponse"},"example":{"code":200,"data":{"JID":"120363000000000011@g.us","OwnerJID":"123456789012340@lid","OwnerPN":"5511977777777@s.whatsapp.net","Name":"Project Team","NameSetAt":"2026-09-15T12:00:00Z","NameSetBy":"123456789012340@lid","NameSetByPN":"5511977777777@s.whatsapp.net","Topic":"Weekly status and deadlines","TopicID":"1757937600000000","TopicSetAt":"2026-09-15T12:05:00Z","TopicSetBy":"123456789012340@lid","TopicSetByPN":"5511977777777@s.whatsapp.net","TopicDeleted":false,"IsLocked":true,"IsAnnounce":false,"AnnounceVersionID":"1757937600000000","IsEphemeral":true,"DisappearingTimer":604800,"IsIncognito":false,"IsParent":false,"DefaultMembershipApprovalMode":"","LinkedParentJID":"120363000000000033@g.us","IsDefaultSubGroup":false,"IsJoinApprovalRequired":true,"AddressingMode":"lid","GroupCreated":"2026-09-15T12:00:00Z","CreatorCountryCode":"BR","ParticipantVersionID":"1757937600000001","Participants":[{"JID":"123456789012340@lid","PhoneNumber":"5511977777777@s.whatsapp.net","LID":"123456789012340@lid","Username":"","IsAdmin":true,"IsSuperAdmin":true,"DisplayName":"","Error":0,"AddRequest":null},{"JID":"123456789012345@lid","PhoneNumber":"5511999999999@s.whatsapp.net","LID":"123456789012345@lid","Username":"","IsAdmin":false,"IsSuperAdmin":false,"DisplayName":"","Error":0,"AddRequest":null}],"ParticipantCount":2,"MemberAddMode":"admin_add","Suspended":false},"success":true}}}},"400":{"description":"Bad Request: `groupJID` is missing or cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_group_jid":{"summary":"groupJID missing","value":{"code":400,"error":"missing groupJID parameter","success":false}},"could_not_parse_group_jid":{"summary":"groupJID is invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or the WhatsApp query failed (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_a_member":{"summary":"Session is not in the group (legacy envelope)","value":{"code":500,"data":"Failed to get group info: you're not participating in that group","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/photo":{"post":{"tags":["Group"],"summary":"Set the group photo","description":"Uploads a new profile photo for a group and returns the WhatsApp picture ID. The image is sent as a base64 data URL\nand must contain JPEG bytes, because WhatsApp only accepts JPEG group photos.\n\n**Rules:**\n- `GroupJID` and `Image` are required.\n- `Image` must start with `data:image` and decode as a data URL; otherwise **400**.\n- The decoded bytes must be JPEG (start with `FF D8 FF`). PNG, GIF or WebP data URLs pass the prefix check but are rejected with **400**, even though the prefix error message lists them.\n- WhatsApp rejects some images with IQ error 406, returned as **500** in the legacy envelope: `failed to set group photo: the given data is not a valid image`. Only JPEG is accepted (despite the list in the prefix error), and even valid JPEGs from some encoders (e.g. ffmpeg with optimized Huffman tables or progressive encoding) are rejected, as are images that are not square or are too small.\n- Recommended: a **baseline** (non-progressive) JPEG, square **640 × 640** px.\n- When the group is locked (`POST /group/locked`), only admins can change the photo.\n\n**Use Cases:**\n- Brand customer groups with the company logo\n- Refresh an event group's cover image\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupPhoto"},"examples":{"jpeg_data_url":{"summary":"JPEG image as a data URL","description":"The base64 payload is shortened here; send the full JPEG file content.","value":{"GroupJID":"120363000000000011@g.us","Image":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAD8AKp//2Q=="}}}}}},"responses":{"200":{"description":"Photo set; `PictureID` is the ID assigned by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupPhotoSetResponse"},"example":{"code":200,"data":{"Details":"Group Photo set successfully","PictureID":"1757862000"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, unparsable `GroupJID`, missing `Image`, not a data URL, empty image, or not a JPEG.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"GroupJID is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}},"missing_image":{"summary":"Image missing","value":{"code":400,"error":"missing Image in Payload","success":false}},"not_a_data_url":{"summary":"Image does not start with data:image","value":{"code":400,"error":"image data should start with \"data:image/\" (supported formats: jpeg, png, gif, webp)","success":false}},"invalid_base64":{"summary":"Data URL cannot be decoded","value":{"code":400,"error":"could not decode base64 encoded data from payload","success":false}},"empty_image":{"summary":"Data URL has no bytes","value":{"code":400,"error":"no image data found in payload","success":false}},"not_jpeg":{"summary":"Decoded image is not a JPEG","value":{"code":400,"error":"image must be in JPEG format. WhatsApp only accepts JPEG images for group photos","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the image (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Image rejected by WhatsApp with IQ 406 (legacy envelope)","description":"Returned for non-JPEG content or JPEGs WhatsApp does not accept (progressive/optimized-Huffman, not square, too small). Re-encode as a baseline 640 × 640 JPEG.","value":{"code":500,"data":"failed to set group photo: the given data is not a valid image","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/leave":{"post":{"tags":["Group"],"summary":"Leave a group","description":"Removes the session from a group. The group keeps existing for the other participants and the chat history stays\non the linked devices.\n\n**Rules:**\n- `GroupJID` is required and should be a group JID (`@g.us`).\n- The gateway does not promote anyone first: if the session is the only admin, promote another member with `POST /group/updateparticipants` before leaving.\n- After leaving, group routes that need membership (info, invite link, settings) fail for this group.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupLeave"},"examples":{"leave":{"summary":"Leave a group","description":"Only the group JID is needed.","value":{"GroupJID":"120363000000000011@g.us"}}}}}},"responses":{"200":{"description":"The session left the group.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group left successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `GroupJID` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"GroupJID is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the request (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Not a member of the group (legacy envelope)","value":{"code":500,"data":"failed to leave group: info query returned status 404: item-not-found","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/name":{"post":{"tags":["Group"],"summary":"Rename a group","description":"Changes the subject (name) of a group. Every participant sees a system message announcing the new name.\n\n**Rules:**\n- `GroupJID` and `Name` are required; an empty `Name` returns **400**.\n- The gateway does not check the length; WhatsApp enforces its own subject limit and rejects longer names with **500** in the legacy envelope.\n- When the group is locked (`POST /group/locked`), only admins can rename it.\n\n**Use Cases:**\n- Include a ticket number or status in a support group name\n- Rename an event group after the date changes\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupName"},"examples":{"rename":{"summary":"Rename a group","description":"Sets a new subject shown to every participant.","value":{"GroupJID":"120363000000000011@g.us","Name":"Customer Success Team"}},"with_status":{"summary":"Name carrying a ticket status","description":"Emoji and digits are allowed in the subject.","value":{"GroupJID":"120363000000000011@g.us","Name":"Ticket 4821 - Resolved ✅"}}}}}},"responses":{"200":{"description":"Group renamed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group Name set successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, unparsable `GroupJID`, or missing `Name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"GroupJID is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}},"missing_name":{"summary":"Name missing or empty","value":{"code":400,"error":"missing Name in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the name (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Not allowed to rename (legacy envelope)","value":{"code":500,"data":"failed to set group name: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/topic":{"post":{"tags":["Group"],"summary":"Set the group description","description":"Changes the description (topic) shown in the group info screen.\n\n**Rules:**\n- `GroupJID` and `Topic` are required. An empty `Topic` returns **400**, so this route cannot clear a description.\n- The gateway does not check the length; WhatsApp enforces its own limit and rejects longer text with **500** in the legacy envelope.\n- When the group is locked (`POST /group/locked`), only admins can change the description.\n\n**Use Cases:**\n- Publish group rules or opening hours\n- Keep a link to the current agenda in a team group\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupTopic"},"examples":{"rules":{"summary":"Publish group rules","description":"Multi-line text is allowed; use `\\n` for line breaks.","value":{"GroupJID":"120363000000000011@g.us","Topic":"Support hours: Mon-Fri, 9am-6pm.\nPlease keep messages on topic."}}}}}},"responses":{"200":{"description":"Description updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group Topic set successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, unparsable `GroupJID`, or missing `Topic`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"GroupJID is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}},"missing_topic":{"summary":"Topic missing or empty","value":{"code":400,"error":"missing Topic in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the description (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Not allowed to change the description (legacy envelope)","value":{"code":500,"data":"failed to set group topic: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/announce":{"post":{"tags":["Group"],"summary":"Allow only admins to send messages","description":"Controls the **Send messages** permission of a group. With announce mode on, only admins can send messages;\nevery member can still read them. The session must be an admin of the group.\n\n**Rules:**\n- `GroupJID` is required and should be a group JID (`@g.us`).\n- `Announce` defaults to `false` when omitted, which lets every member send messages again.\n- Read the current state from `GET /group/info` (`IsAnnounce`).\n\n**Use Cases:**\n- Broadcast-style groups for announcements and newsletters\n- Temporarily mute a group during a live event\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupAnnounce"},"examples":{"admins_only":{"summary":"Only admins can send messages","description":"Turns announce mode on.","value":{"GroupJID":"120363000000000011@g.us","Announce":true}},"everyone":{"summary":"Every member can send messages","description":"Turns announce mode off.","value":{"GroupJID":"120363000000000011@g.us","Announce":false}}}}}},"responses":{"200":{"description":"WhatsApp accepted the new announce setting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group Announce set successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `GroupJID` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"GroupJID is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the change (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"Session is not an admin (legacy envelope)","value":{"code":500,"data":"failed to set group announce: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/memberaddmode":{"post":{"tags":["Group"],"summary":"Set who can add members to a group","description":"Changes the **Add other members** permission of a group: either every member or only admins can add new participants.\nThe gateway sends the `member_add_mode` group IQ; the session must be an admin of the group for WhatsApp to accept it.\n\n**Rules:**\n- `groupjid` and `mode` are required. `mode` is validated first: any value other than `admin_add` or `all_member_add` returns **400** before the JID is parsed.\n- `groupjid` should be a group JID (`@g.us`). A value without `@` is parsed as a phone number and is rejected by WhatsApp, not by the gateway.\n\n**Use Cases:**\n- Lock membership growth of a support group to admins\n- Let every member invite colleagues in an internal team group\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupMemberAddMode"},"examples":{"admins_only":{"summary":"Only admins can add members","description":"Sets the \"Add other members\" permission to admins only.","value":{"groupjid":"120363000000000011@g.us","mode":"admin_add"}},"all_members":{"summary":"All members can add members","description":"Allows every participant to add new members.","value":{"groupjid":"120363000000000011@g.us","mode":"all_member_add"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the new member add mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group member add mode set successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `mode` is not an accepted value, or `groupjid` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"invalid_mode":{"summary":"mode is missing or not accepted","value":{"code":400,"error":"invalid mode, must be 'admin_add' or 'all_member_add'","success":false}},"could_not_parse_group_jid":{"summary":"groupjid is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the change (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"WhatsApp rejected the change (legacy envelope)","value":{"code":500,"data":"failed to set group member add mode: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/joinapproval":{"post":{"tags":["Group"],"summary":"Turn admin approval for new members on or off","description":"Changes the **Approve new members** permission of a group. When it is on, people joining through an invite link\nbecome pending requests that an admin must approve (see `POST /community/requests` and `POST /community/requests/update`).\nThe gateway sends the `membership_approval_mode` group IQ; the session must be an admin of the group.\n\n**Rules:**\n- `groupjid` is required. `require_approval` defaults to `false` when omitted, so an empty body field turns approval **off**.\n\n**Use Cases:**\n- Screen who enters a public group shared by link\n- Reopen a group for direct joins after an event ends\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupJoinApproval"},"examples":{"require":{"summary":"Require admin approval","description":"New members who use an invite link wait for an admin to approve them.","value":{"groupjid":"120363000000000011@g.us","require_approval":true}},"open":{"summary":"Join without approval","description":"Anyone with a valid invite link joins immediately.","value":{"groupjid":"120363000000000011@g.us","require_approval":false}}}}}},"responses":{"200":{"description":"WhatsApp accepted the new join approval mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group join approval mode set successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `groupjid` cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"groupjid is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the change (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"whatsapp_rejected":{"summary":"WhatsApp rejected the change (legacy envelope)","value":{"code":500,"data":"failed to set group join approval mode: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/join":{"post":{"tags":["Group"],"summary":"Join a group with an invite link","description":"Joins a group using an invite code or a full `https://chat.whatsapp.com/...` link. Preview the group first with\n`POST /group/inviteinfo` if needed.\n\n**Rules:**\n- `Code` is required. The `https://chat.whatsapp.com/` prefix and any query string are stripped by the library.\n- The response only confirms the join; it does not include the group JID. Use `POST /group/inviteinfo` or `GET /group/list` to obtain it.\n- When the group requires admin approval, WhatsApp only registers a **pending join request** instead of adding the session, and the response is identical (`{\"Details\":\"Group joined successfully\"}`). Check `IsJoinApprovalRequired` via `POST /group/inviteinfo` before joining, and confirm membership afterwards with `GET /group/list` (the group only appears once an admin approves).\n- Revoked or malformed links return **500** in the legacy envelope with the WhatsApp reason.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupJoin"},"examples":{"code":{"summary":"Invite code only","description":"The part after `chat.whatsapp.com/`.","value":{"Code":"AbCdEfGhIjKlMnOpQrStUv"}},"full_link":{"summary":"Full invite link","description":"The link prefix is removed before the request is sent.","value":{"Code":"https://chat.whatsapp.com/AbCdEfGhIjKlMnOpQrStUv"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the join, or registered a pending join request when the group requires admin approval (same body in both cases; confirm with `GET /group/list`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group joined successfully"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `Code` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_code":{"summary":"Code missing or empty","value":{"code":400,"error":"missing Code in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp refused the join (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"link_revoked":{"summary":"Link revoked (legacy envelope)","value":{"code":500,"data":"failed to join group: that group invite link has been revoked","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/inviteinfo":{"post":{"tags":["Group"],"summary":"Preview a group from its invite link","description":"Returns the `GroupInfo` of a group from an invite code or link **without joining it**, so the name, description,\nsize and settings can be checked first.\n\n**Rules:**\n- `Code` is required. The `https://chat.whatsapp.com/` prefix and any query string are stripped by the library.\n- Fields WhatsApp does not share with non-members come back empty, zero or `null` (the participant list is often `null`).\n- `IsJoinApprovalRequired: true` means `POST /group/join` will only create a pending request that an admin must approve.\n- Revoked or malformed links return **500** in the legacy envelope with the WhatsApp reason.\n- A participant **removed by an admin** can neither preview nor rejoin through the invite link: WhatsApp answers 401 `not-authorized` (**500** legacy envelope). An admin must re-add them with `POST /group/updateparticipants`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupInviteInfo"},"examples":{"code":{"summary":"Invite code only","description":"The part after `chat.whatsapp.com/`.","value":{"Code":"AbCdEfGhIjKlMnOpQrStUv"}},"full_link":{"summary":"Full invite link","description":"The link prefix is removed before the query is sent.","value":{"Code":"https://chat.whatsapp.com/AbCdEfGhIjKlMnOpQrStUv"}}}}}},"responses":{"200":{"description":"Group preview.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupInfoResponse"},"example":{"code":200,"data":{"JID":"120363000000000011@g.us","OwnerJID":"123456789012340@lid","OwnerPN":"","Name":"Project Team","NameSetAt":"2026-09-15T12:00:00Z","NameSetBy":"","NameSetByPN":"","Topic":"Weekly status and deadlines","TopicID":"","TopicSetAt":"2026-09-15T12:05:00Z","TopicSetBy":"","TopicSetByPN":"","TopicDeleted":false,"IsLocked":true,"IsAnnounce":false,"AnnounceVersionID":"","IsEphemeral":false,"DisappearingTimer":0,"IsIncognito":false,"IsParent":false,"DefaultMembershipApprovalMode":"","LinkedParentJID":"","IsDefaultSubGroup":false,"IsJoinApprovalRequired":true,"AddressingMode":"lid","GroupCreated":"2026-09-15T12:00:00Z","CreatorCountryCode":"","ParticipantVersionID":"","Participants":null,"ParticipantCount":12,"MemberAddMode":"","Suspended":false},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `Code` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_code":{"summary":"Code missing or empty","value":{"code":400,"error":"missing Code in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp refused the query (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"link_invalid":{"summary":"Malformed link (legacy envelope)","value":{"code":500,"data":"failed to get group invite info: that group invite link is not valid","success":true}},"removed_by_admin":{"summary":"Session was removed from the group by an admin (legacy envelope)","description":"A participant removed by an admin cannot preview or rejoin via the link; an admin must re-add them.","value":{"code":500,"data":"failed to get group invite info: info query returned status 401: not-authorized","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/updateparticipants":{"post":{"tags":["Group"],"summary":"Add, remove, promote or demote group participants","description":"Applies one participant action to a list of people in a group: add them, remove them, promote them to admin or\ndemote them. The session must be an admin of the group.\n\n**Rules:**\n- `GroupJID`, `Phone` (at least one entry) and `Action` are required. `Action` is case-sensitive: `add`, `remove`, `promote` or `demote`.\n- Validation order: `GroupJID`, then `Phone`, then `Action`. One unparsable phone aborts the request with **400**.\n- **200 does not mean every participant changed.** WhatsApp answers per participant, but this route discards that list; confirm with `GET /group/info`.\n- Whole-request failures (not an admin, not a member) return **500** in the legacy envelope with the WhatsApp reason.\n\n**Use Cases:**\n- Add a new customer contact to an existing support group\n- Promote a colleague to admin before leaving a group\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGroupParticipants"},"examples":{"add":{"summary":"Add two participants","description":"Phone numbers with country code; user JIDs also work.","value":{"GroupJID":"120363000000000011@g.us","Phone":["5511999999999","5511988888888"],"Action":"add"}},"remove":{"summary":"Remove a participant","description":"Removes one member from the group.","value":{"GroupJID":"120363000000000011@g.us","Phone":["5511988888888"],"Action":"remove"}},"promote":{"summary":"Promote to admin","description":"Keys are matched case-insensitively; LIDs are accepted.","value":{"groupjid":"120363000000000011@g.us","phone":["123456789012345@lid"],"action":"promote"}},"demote":{"summary":"Demote an admin","description":"The participant stays in the group as a regular member.","value":{"GroupJID":"120363000000000011@g.us","Phone":["5511999999999"],"Action":"demote"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the request. Per-participant results are not returned.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group Participants updated successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, unparsable `GroupJID`, missing or invalid `Phone`, or missing or unknown `Action`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"could_not_parse_group_jid":{"summary":"GroupJID is missing or invalid","value":{"code":400,"error":"could not parse Group JID","success":false}},"missing_phone":{"summary":"Phone missing or empty","value":{"code":400,"error":"missing Phone in Payload","success":false}},"invalid_phone":{"summary":"A phone is not a valid number or JID","value":{"code":400,"error":"could not parse Phone","success":false}},"missing_action":{"summary":"Action missing","value":{"code":400,"error":"missing Action in Payload","success":false}},"invalid_action":{"summary":"Action not accepted","value":{"code":400,"error":"invalid Action in Payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session (plain error), or WhatsApp rejected the request (legacy envelope with the text in `data` and `success: true`).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/LegacyErrorEnvelope"}]},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_admin":{"summary":"Session is not an admin (legacy envelope)","value":{"code":500,"data":"failed to change participant group: info query returned status 403: forbidden","success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/status/send/text":{"post":{"tags":["Status"],"summary":"Post a text status","description":"Posts a text status (story) to `status@broadcast`, with optional background color, text color and font. It stays visible to the chosen audience for 24 hours.\n\n**Rules:**\n- `text` is required. WhatsApp limits status text to about 650 characters; the gateway does not truncate or check the length.\n- `background_color` and `text_color` are ARGB colors written as unsigned decimal strings (for example `4278190080` is opaque black). Values that do not parse are silently ignored.\n- `font` accepts 0-10; `0` (system font) is used when omitted, and values outside the range are ignored.\n- `audience` limits the text status to individual contacts (phone digits, `@s.whatsapp.net` or `@lid`, no devices or groups); `exclude_list` removes contacts. Omit both to follow the account's status privacy.\n- Entries that are not individual contacts are ignored with a warning; an empty or entirely invalid `audience` uses the account's status privacy. A valid `audience` or `exclude_list` is never widened: if it cannot be applied (nobody remains after `exclude_list`, or a contact cannot be resolved) the status is **not** sent and the route returns **500** `failed to send text status: ... (status audience could not be applied; the status was not sent)`. The audience never causes a **400**.\n- `id` sets a custom message ID; otherwise one is generated.\n\n**Fonts:**\n- `0` SYSTEM, `1` SYSTEM_TEXT, `2` FB_SCRIPT, `6` SYSTEM_BOLD\n- `7` MORNINGBREEZE_REGULAR, `8` CALISTOGA_REGULAR, `9` EXO2_EXTRABOLD, `10` COURIERPRIME_BOLD\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusText"},"examples":{"simple":{"summary":"Plain text status","description":"Uses the system font and default colors, visible according to the status privacy setting.","value":{"text":"Store open until 10 PM today!"}},"styled":{"summary":"Colored background and custom font","description":"Opaque blue background, white text and the CALISTOGA_REGULAR font.","value":{"text":"New collection available now","background_color":"4280391411","text_color":"4294967295","font":8}},"restricted_audience":{"summary":"Visible only to selected contacts","description":"`audience` limits who sees the status; `exclude_list` removes one of them.","value":{"text":"Private update for the team","audience":["5511999999999","5511888888888@s.whatsapp.net","123456789012345@lid"],"exclude_list":["5511888888888"]}}}}}},"responses":{"200":{"description":"The text status was sent and acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSendResponse"},"example":{"code":200,"data":{"message_id":"3EB06F9067F80BAB89FF","timestamp":"2026-09-15T10:30:00-03:00","status":"sent","type":"text_status"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `text` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_request_body":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"text_is_required":{"summary":"text missing","value":{"code":400,"error":"text is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp client for this user, the client is not connected, or the text status could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp client for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send text status: context deadline exceeded","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/status/send/image":{"post":{"tags":["Status"],"summary":"Post an image status","description":"Uploads an image and posts it as a status (story) to `status@broadcast`, with an optional caption. It stays visible to the chosen audience for 24 hours.\n\n**Rules:**\n- `image` is required and accepts a base64 data URL (`data:image/jpeg;base64,...`) or an HTTP(S) URL that the gateway downloads. JPEG and PNG are the safest formats.\n- An image that cannot be decoded or downloaded returns **400** `failed to process image: ...`; an upload failure returns **500**.\n- `audience` restricts the image status to individual contacts (phone digits, `@s.whatsapp.net` or `@lid`) and `exclude_list` removes contacts; without them the account's status privacy applies; entries that are not individual contacts are ignored with a warning; an empty or entirely invalid `audience` uses the account's status privacy. A valid `audience` or `exclude_list` is never widened: if it cannot be applied (nobody remains after `exclude_list`, or a contact cannot be resolved) the status is **not** sent and the route returns **500** `failed to send image status: ... (status audience could not be applied; the status was not sent)`. The audience never causes a **400**.\n- Upload and send share a 60-second timeout. `id` sets a custom message ID.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusImage"},"examples":{"from_url":{"summary":"Image from a public URL with caption","description":"The gateway downloads the image before uploading it to WhatsApp.","value":{"image":"https://example.com/media/weekly-offer.jpg","caption":"This week's offer"}},"base64_restricted":{"summary":"Base64 image for selected contacts","description":"Inline data URL shown only to the listed contacts.","value":{"image":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","caption":"Preview for VIP customers","audience":["5511999999999","123456789012345@lid"]}}}}}},"responses":{"200":{"description":"The image was uploaded and the status acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSendResponse"},"example":{"code":200,"data":{"message_id":"3EB0A3C4D5E6F7A8B9C0","timestamp":"2026-09-15T10:31:00-03:00","status":"sent","type":"image_status"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `image` is missing or cannot be processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_request_body":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"image_is_required":{"summary":"image missing","value":{"code":400,"error":"image is required","success":false}},"invalid_media_input":{"summary":"image is neither a data URL nor an HTTP(S) URL","value":{"code":400,"error":"failed to process image: invalid media input: must be either base64 data URL or HTTP(S) URL","success":false}},"download_http_error":{"summary":"Image URL returned an HTTP error","value":{"code":400,"error":"failed to process image: HTTP error 404 when downloading from URL","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp client, the client is not connected, or the image upload or status send failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp client for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"upload_failed":{"summary":"Upload to WhatsApp failed","value":{"code":500,"error":"failed to upload image: context deadline exceeded","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send image status: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/status/send/video":{"post":{"tags":["Status"],"summary":"Post a video status","description":"Uploads a video and posts it as a status (story) to `status@broadcast`, with an optional caption. It stays visible to the chosen audience for 24 hours.\n\n**Rules:**\n- `video` is required and accepts a base64 data URL (`data:video/mp4;base64,...`) or an HTTP(S) URL. Use MP4 with H.264 video and AAC audio for playback on every device.\n- The duration is read from the MP4 header when possible; WhatsApp limits video statuses to short clips (about 60 seconds).\n- A video that cannot be decoded or downloaded returns **400** `failed to process video: ...`; an upload failure returns **500**.\n- For a video status, `audience` accepts only individual contacts (phone digits, `@s.whatsapp.net` or `@lid`) and `exclude_list` subtracts from it; omitted, the account's status privacy decides; entries that are not individual contacts are ignored with a warning; an empty or entirely invalid `audience` uses the account's status privacy. A valid `audience` or `exclude_list` is never widened: if it cannot be applied (nobody remains after `exclude_list`, or a contact cannot be resolved) the status is **not** sent and the route returns **500** `failed to send video status: ... (status audience could not be applied; the status was not sent)`. The audience never causes a **400**.\n- Upload and send share a 120-second timeout. `id` sets a custom message ID.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusVideo"},"examples":{"from_url":{"summary":"MP4 from a public URL with caption","description":"The gateway downloads the video before uploading it to WhatsApp.","value":{"video":"https://example.com/media/product-demo.mp4","caption":"30-second product demo"}},"base64_with_exclusion":{"summary":"Base64 video hidden from one contact","description":"No `audience`, so the status privacy applies, minus the excluded contact.","value":{"video":"data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAu1tZGF0","caption":"Behind the scenes","exclude_list":["5511888888888"]}}}}}},"responses":{"200":{"description":"The video was uploaded and the status acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSendResponse"},"example":{"code":200,"data":{"message_id":"3EB0B4C5D6E7F8A9B0C1","timestamp":"2026-09-15T10:32:00-03:00","status":"sent","type":"video_status"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `video` is missing or cannot be processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_request_body":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"video_is_required":{"summary":"video missing","value":{"code":400,"error":"video is required","success":false}},"invalid_base64":{"summary":"Data URL with invalid base64","value":{"code":400,"error":"failed to process video: could not decode base64 data: illegal base64 data at input byte 12","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp client, the client is not connected, or the video upload or status send failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp client for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"upload_failed":{"summary":"Upload to WhatsApp failed","value":{"code":500,"error":"failed to upload video: context deadline exceeded","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send video status: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/status/send/audio":{"post":{"tags":["Status"],"summary":"Post an audio or voice note status","description":"Uploads audio and posts it as a status (story) to `status@broadcast`, either as a voice note or as an audio file. A waveform is always generated.\n\n**Rules:**\n- `audio` is required and accepts a base64 data URL or an HTTP(S) URL.\n- **Voice note (`ptt: true`, default):** send OGG/Opus. The MIME type is normalized to exactly `audio/ogg; codecs=opus`, because the official apps silently drop voice-note statuses with any other MIME type.\n- **Audio file (`ptt: false`):** MP3, M4A/AAC or OGG; unknown types fall back to `audio/mpeg`.\n- Audio statuses honor `audience` (individual phone digits, `@s.whatsapp.net` or `@lid` only) and `exclude_list`; leaving both out uses the account's status privacy; entries that are not individual contacts are ignored with a warning; an empty or entirely invalid `audience` uses the account's status privacy. A valid `audience` or `exclude_list` is never widened: if it cannot be applied (nobody remains after `exclude_list`, or a contact cannot be resolved) the status is **not** sent and the route returns **500** `failed to send audio status: ... (status audience could not be applied; the status was not sent)`. The audience never causes a **400**.\n- The response reports the final `mime_type`, the `duration` in seconds and `has_waveform`. Upload and send share a 60-second timeout.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusAudio"},"examples":{"voice_note":{"summary":"Voice note status from OGG/Opus","description":"`ptt` defaults to true, so this is posted as a voice note.","value":{"audio":"data:audio/ogg;base64,T2dnUwACAAAAAAAAAAAAAAAAAAAAAMhHv8oBE09wdXNIZWFkAQE4AYC7AAAAAABPZ2dT"}},"audio_file_from_url":{"summary":"MP3 audio file for selected contacts","description":"`ptt: false` posts a regular audio file instead of a voice note.","value":{"audio":"https://example.com/media/jingle.mp3","ptt":false,"audience":["5511999999999"]}}}}}},"responses":{"200":{"description":"The audio was uploaded and the status acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSendAudioResponse"},"examples":{"voice_note":{"summary":"Voice note posted","value":{"code":200,"data":{"message_id":"3EB072C49492CB69CBCBCF","timestamp":"2026-09-14T22:25:15-03:00","status":"sent","type":"voice_status","ptt":true,"duration":4,"has_waveform":true,"mime_type":"audio/ogg; codecs=opus"},"success":true}},"audio_file":{"summary":"Audio file posted","value":{"code":200,"data":{"message_id":"3EB072C49492CB69CBCBD0","timestamp":"2026-09-14T22:26:40-03:00","status":"sent","type":"audio_status","ptt":false,"duration":32,"has_waveform":true,"mime_type":"audio/mpeg"},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON or `audio` is missing or cannot be processed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_request_body":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"audio_is_required":{"summary":"audio missing","value":{"code":400,"error":"audio is required","success":false}},"download_failed":{"summary":"Audio URL could not be downloaded","value":{"code":400,"error":"failed to process audio: HTTP error 403 when downloading from URL","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp client, the client is not connected, or the audio upload or status send failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp client for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"upload_failed":{"summary":"Upload to WhatsApp failed","value":{"code":500,"error":"failed to upload audio: context deadline exceeded","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send audio status: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/reject/send":{"post":{"tags":["Call"],"summary":"Reject a call and send a follow-up text (legacy)","description":"Rejects an incoming call through the WhatsApp session and, when `message` is set, sends it to the caller\nas a plain text message. This is the original rejection route; `POST /call/reject` is the newer variant\nwith a default `reject_type` and an honest `message_sent` flag.\n\n**Rules:**\n- `call_id`, `call_from` and `reject_type` are required. `reject_type` has no default here: omitting it returns **400**.\n- `call_from` must be the caller JID exactly as received in the call offer webhook (for example `5511999999999@s.whatsapp.net` or `123456789012345@lid`).\n- The session must exist and be connected; that is checked **before** the body is read, so a disconnected session answers **500** even for an invalid body.\n- `reject_type` is validated and echoed back, but the rejection stanza sent to WhatsApp is the same for all three values.\n- The follow-up text is best effort: a failed send is only logged, and `message_sent` is still `true` whenever `message` was provided.\n\n**Use Cases:**\n- Auto-reply \"I'm in a meeting, I'll call you back\" when declining a call\n- Keep integrations built on the original route working unchanged\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallRejectRequest"},"examples":{"busy_with_message":{"summary":"Reject as busy with a follow-up text","description":"Declines the call and sends a short text to the caller right after.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reject_type":"busy","message":"I'm in a meeting right now, I'll call you back soon."}},"declined_silently":{"summary":"Reject without a message","description":"Declines the call and sends nothing else; `message_sent` is omitted from the response.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid","reject_type":"declined"}}}}}},"responses":{"200":{"description":"Rejection stanza sent. `message_sent` is only present when `message` was provided.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallRejectLegacyResponse"},"examples":{"with_message":{"summary":"Rejected with a follow-up text","value":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reject_type":"busy","action":"rejected","message_sent":true},"success":true}},"without_message":{"summary":"Rejected without a message","value":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid","reject_type":"declined","action":"rejected"},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, a required field is missing, `reject_type` is not allowed, or `call_from` is not a parseable JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"missing_fields":{"summary":"call_id or call_from missing","value":{"code":400,"error":"call_id and call_from are required","success":false}},"invalid_reject_type":{"summary":"reject_type missing or not allowed","value":{"code":400,"error":"invalid reject_type, must be: busy, declined, or unavailable","success":false}},"invalid_call_from":{"summary":"call_from is not a valid JID","value":{"code":400,"error":"invalid call_from JID: unexpected number of dots in JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the session is disconnected, or WhatsApp did not accept the rejection.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Session is not connected","value":{"code":500,"error":"client not connected","success":false}},"reject_failed":{"summary":"Rejection stanza failed","value":{"code":500,"error":"failed to reject call: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/reject":{"post":{"tags":["Call"],"summary":"Reject an incoming call","description":"Sends a reject stanza for an inbound call offer through the WhatsApp session, optionally followed by a text\nmessage to the caller. Works without the native calls engine: only a connected session is needed.\n\n**Rules:**\n- `call_id` and `call_from` are required; both come from the call offer webhook.\n- `reject_type` defaults to `declined` and must be `busy`, `declined` or `unavailable`. It is echoed back; the stanza itself is the same for all values.\n- The body is validated first (JSON and `reject_type`), then the session (**500** when missing or disconnected), then `call_id`/`call_from`.\n- `message_sent` reports the real outcome of the follow-up text: `false` when no message was requested or when sending it failed. A failed follow-up never turns the response into an error.\n- The response `call_from` is the normalized JID string.\n\n**Use Cases:**\n- Decline calls outside business hours and point the caller to chat\n- Signal \"busy\" from a contact-center integration\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallRejectV1Request"},"examples":{"declined_default":{"summary":"Reject with the default type","description":"`reject_type` is omitted, so `declined` is used and no follow-up text is sent.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net"}},"declined_with_followup":{"summary":"Reject and send a follow-up text","description":"Rejects as `unavailable` and sends a text to the caller; `message_sent` tells whether the text went out.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid","reject_type":"unavailable","message":"We can't take calls right now. Please send us a message and we'll reply shortly."}}}}}},"responses":{"200":{"description":"Reject stanza sent; `message_sent` reports whether the optional follow-up text was delivered to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallRejectV1Response"},"examples":{"rejected_with_followup":{"summary":"Rejected and follow-up sent","value":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid","reject_type":"unavailable","action":"rejected","message_sent":true},"success":true}},"rejected_only":{"summary":"Rejected without follow-up","value":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reject_type":"declined","action":"rejected","message_sent":false},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, `reject_type` is not allowed, a required field is missing, or `call_from` is not a parseable JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"invalid_reject_type":{"summary":"reject_type not allowed","value":{"code":400,"error":"invalid reject_type, must be busy|declined|unavailable","success":false}},"missing_fields":{"summary":"call_id or call_from missing","value":{"code":400,"error":"call_id and call_from are required","success":false}},"invalid_call_from":{"summary":"call_from is not a valid JID","value":{"code":400,"error":"invalid call_from JID: unexpected number of dots in JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the session is disconnected, or WhatsApp did not accept the rejection.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Session is not connected","value":{"code":500,"error":"client not connected","success":false}},"reject_failed":{"summary":"Rejection stanza failed","value":{"code":500,"error":"failed to reject call: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/accept":{"post":{"tags":["Call"],"summary":"Send an accept stanza for an incoming call","description":"Sends the signaling `accept` stanza for an inbound call offer through the WhatsApp session. It only answers\nat the protocol level: no audio or video media is set up by this route. To answer a call with real media,\nenable the native calls engine and use `POST /call/answer`.\n\n**Rules:**\n- `call_id` and `call_from` are required; take both from the call offer webhook.\n- The session must exist and be connected (**500** otherwise); this is checked after the JSON body is decoded and before the required fields.\n- Nothing is stored and no call metrics are produced; the call lifecycle keeps arriving through webhooks.\n- Accepting the same call twice is forwarded to WhatsApp again; the gateway does not de-duplicate.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAcceptV1Request"},"examples":{"accept":{"summary":"Accept a call offer","description":"Uses the call ID and caller JID from the call offer webhook.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net"}}}}}},"responses":{"200":{"description":"Accept stanza sent to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAcceptV1Response"},"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","action":"accepted"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `call_id`/`call_from` is missing, or `call_from` is not a parseable JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"missing_fields":{"summary":"call_id or call_from missing","value":{"code":400,"error":"call_id and call_from are required","success":false}},"invalid_call_from":{"summary":"call_from is not a valid JID","value":{"code":400,"error":"invalid call_from JID: unexpected number of dots in JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the session is disconnected, or WhatsApp did not accept the stanza.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Session is not connected","value":{"code":500,"error":"client not connected","success":false}},"accept_failed":{"summary":"Accept stanza failed","value":{"code":500,"error":"failed to accept call: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/preaccept":{"post":{"tags":["Call"],"summary":"Send a pre-accept (ringing) stanza for an incoming call","description":"Sends the signaling `preaccept` stanza for an inbound call offer, which tells the caller that this device\nis ringing. It does not answer the call and sets up no media.\n\n**Rules:**\n- `call_id` and `call_from` are required; take both from the call offer webhook.\n- Send it before `POST /call/accept` or `POST /call/reject`; the gateway does not enforce the order.\n- The session must exist and be connected (**500** otherwise).\n- Nothing is stored; the call keeps its lifecycle in WhatsApp and the webhooks.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAcceptV1Request"},"examples":{"preaccept":{"summary":"Signal ringing for a call offer","description":"Uses the call ID and caller LID from the call offer webhook.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"Pre-accept stanza sent to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallAcceptV1Response"},"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid","action":"preaccepted"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `call_id`/`call_from` is missing, or `call_from` is not a parseable JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"missing_fields":{"summary":"call_id or call_from missing","value":{"code":400,"error":"call_id and call_from are required","success":false}},"invalid_call_from":{"summary":"call_from is not a valid JID","value":{"code":400,"error":"invalid call_from JID: unexpected number of dots in JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the session is disconnected, or WhatsApp did not accept the stanza.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Session is not connected","value":{"code":500,"error":"client not connected","success":false}},"preaccept_failed":{"summary":"Pre-accept stanza failed","value":{"code":500,"error":"failed to preaccept call: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/terminate":{"post":{"tags":["Call"],"summary":"Send a terminate stanza for a call","description":"Sends the signaling `terminate` stanza for a call through the WhatsApp session, ending it at the protocol\nlevel. Use it for calls handled by signaling only; calls tracked by the native calls engine are ended with\n`POST /call/hangup`, which also tears down their media.\n\n**Rules:**\n- `call_id` and `call_from` are required; `call_from` is the other party's JID from the call webhook.\n- `reason` is free text forwarded to WhatsApp and defaults to `hangup`.\n- The session must exist and be connected (**500** otherwise).\n- No duration or call record is produced here; the `CallTerminate` webhook event reports the end of the call.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTerminateRequest"},"examples":{"hangup":{"summary":"End a call with the default reason","description":"`reason` is omitted, so `hangup` is sent.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net"}},"custom_reason":{"summary":"End a call with an explicit reason","description":"The reason string is forwarded unchanged and echoed in the response.","value":{"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"123456789012345@lid","reason":"timeout"}}}}}},"responses":{"200":{"description":"Terminate stanza sent to WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTerminateV1Response"},"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reason":"hangup","action":"terminated"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `call_id`/`call_from` is missing, or `call_from` is not a parseable JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"missing_fields":{"summary":"call_id or call_from missing","value":{"code":400,"error":"call_id and call_from are required","success":false}},"invalid_call_from":{"summary":"call_from is not a valid JID","value":{"code":400,"error":"invalid call_from JID: unexpected number of dots in JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the session is disconnected, or WhatsApp did not accept the stanza.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"client_not_initialized":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"client not initialized","success":false}},"client_not_connected":{"summary":"Session is not connected","value":{"code":500,"error":"client not connected","success":false}},"terminate_failed":{"summary":"Terminate stanza failed","value":{"code":500,"error":"failed to terminate call: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/initiate":{"post":{"tags":["Call"],"summary":"Legacy outbound call route (501 unless the dial alias is enabled)","description":"Legacy route. By default it keeps its original contract and answers **501** `make_call_not_implemented` for any body,\nwithout dialing. Place outbound 1:1 calls with `POST /call/dial`.\n\n**Rules:**\n- Default: always **501**. The legacy envelope carries `data.error` = `make_call_not_implemented`, `data.reason` pointing to `/call/dial`, and `success: true` (unchanged legacy flag).\n- Opt-in: when the instance sets `GLOBAL_CALL_INITIATE_DIAL_ALIAS=true`, this route becomes an exact alias of `POST /call/dial` (same request, response and errors: `phone` required, `video` optional, **409** without the calls engine, **502** when the call cannot be placed).\n- A group JID is not a valid target; use `/call/group/dial-by-id` for groups.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDialRequest"},"examples":{"audio_call":{"summary":"Voice call to a phone number","description":"The number is resolved to the callee's LID before dialing.","value":{"phone":"5511988888888"}},"video_call_lid":{"summary":"Video call to a LID","description":"A value containing `@` is used as given; `video` offers H.264 video.","value":{"phone":"123456789012345@lid","video":true}}}}}},"responses":{"200":{"description":"Only with `GLOBAL_CALL_INITIATE_DIAL_ALIAS=true`: outbound call placed; use `data.callId` with the other `/call/*` controls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdResponse"},"example":{"code":200,"data":{"callId":"call_22A9E1B7D3F84C10"},"success":true}}}},"400":{"description":"Only with `GLOBAL_CALL_INITIATE_DIAL_ALIAS=true`. Bad Request: the body is not valid JSON or `phone` is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"phone is required","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Only with `GLOBAL_CALL_INITIATE_DIAL_ALIAS=true`. Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"501":{"description":"Not Implemented (default): this legacy route does not dial; use `POST /call/dial` or enable `GLOBAL_CALL_INITIATE_DIAL_ALIAS=true`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyErrorEnvelope"},"example":{"code":501,"data":{"error":"make_call_not_implemented","reason":"originating a call requires a WebRTC media stack not available in this build"},"success":true}}}},"502":{"description":"Only with `GLOBAL_CALL_INITIATE_DIAL_ALIAS=true`. Bad Gateway: the engine could not place the call (peer unreachable, not on WhatsApp, or refused).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"usync returned no LID for 5511988888888 (peer unreachable or not on WhatsApp)","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/config":{"get":{"tags":["Call"],"summary":"Get the native calls engine configuration","description":"Returns the native calls engine configuration stored for this instance: whether the engine is enabled,\nhow inbound calls are handled, auto-recording, and the voice-agent provider settings.\n\n**Rules:**\n- Reads the saved database row, not the running engine. `callRecord` from `PUT /call/config` is already in effect; the other fields take effect after the instance reconnects.\n- `callProviderToken` is write-only and never returned.\n- Unset provider fields (`callSttUrl`, `callLlmUrl`, `callTtsUrl`, `callSystemPrompt`, `callGreeting`) are returned as empty strings.\n- `callInboundMode` falls back to `webhook` when it was never saved.\n- Works whether or not the engine is enabled; it never answers **409**.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored native calls engine configuration.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEngineConfigResponse"},"examples":{"webhook_mode":{"summary":"Engine enabled, calls answered and reported by webhook","value":{"code":200,"data":{"callsEnabled":true,"callInboundMode":"webhook","callRecord":true,"callSttUrl":"","callLlmUrl":"","callTtsUrl":"","callSystemPrompt":"","callGreeting":""},"success":true}},"disabled":{"summary":"Engine disabled (defaults)","value":{"code":200,"data":{"callsEnabled":false,"callInboundMode":"webhook","callRecord":false,"callSttUrl":"","callLlmUrl":"","callTtsUrl":"","callSystemPrompt":"","callGreeting":""},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration row could not be read from the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"sql: no rows in result set","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"put":{"tags":["Call"],"summary":"Update the native calls engine configuration","description":"Saves the native calls engine configuration for this instance. `callRecord` applies to the running engine\nimmediately: the next answered call records (or not), and `POST /call/record/start` follows it. A recording\nalready in progress is not cut. Every other field is read when the WhatsApp session connects, so reconnect\nthe instance (`POST /session/disconnect` then `POST /session/connect`) for those to apply.\n\n**Rules:**\n- This is a full replace, not a merge: an omitted `callsEnabled` or `callRecord` is saved as `false`, and an omitted `callSttUrl`, `callLlmUrl`, `callTtsUrl`, `callSystemPrompt` or `callGreeting` is cleared.\n- `callProviderToken` is the only field kept when omitted; send a new value to replace it.\n- `callInboundMode` defaults to `webhook` when empty and must be `manual`, `bot`, `ivr`, `ai`, `webhook` or `reject` (**400** otherwise).\n- `bot`, `ivr` and `ai` are accepted but the voice-agent is not available in this build: inbound calls in those modes are rejected by the engine.\n- The request body is an object; send `{}` to reset everything except the provider token.\n\n**Inbound modes:**\n- `webhook`: the engine answers and reports the lifecycle (and the recording when `callRecord` is on) through webhooks.\n- `manual`: the call rings; your application answers with `POST /call/answer` and drives media through the API and streams.\n- `reject`: the engine is not started at all, even with `callsEnabled: true`; every engine endpoint (`/call/dial`, `/call/status`, streams...) then answers **409**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEngineConfig"},"examples":{"enable_webhook_recording":{"summary":"Enable the engine and record every answered call","description":"Inbound calls are answered automatically, recorded to S3 and reported by webhook.","value":{"callsEnabled":true,"callInboundMode":"webhook","callRecord":true}},"enable_manual":{"summary":"Enable the engine in manual mode","description":"Calls ring until the application answers them with `POST /call/answer`.","value":{"callsEnabled":true,"callInboundMode":"manual","callRecord":false}},"voice_agent_settings":{"summary":"Save voice-agent provider settings","description":"Stores provider endpoints and prompts. The `ai` mode is accepted, but inbound calls are rejected because the voice-agent is not available in this build.","value":{"callsEnabled":true,"callInboundMode":"ai","callRecord":false,"callSttUrl":"https://stt.example.com/v1/transcribe","callLlmUrl":"https://llm.example.com/v1/chat","callTtsUrl":"https://tts.example.com/v1/speak","callProviderToken":"sk-example-provider-token","callSystemPrompt":"You are the virtual receptionist of Example Store. Be brief and friendly.","callGreeting":"Hello! Thanks for calling Example Store. How can I help you?"}},"disable":{"summary":"Disable the engine","description":"Saves the engine as disabled; the provider token is kept, every other field is reset.","value":{"callsEnabled":false}}}}}},"responses":{"200":{"description":"Configuration saved. It applies on the next reconnect.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `callInboundMode` is not an accepted mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_body":{"summary":"Body is not valid JSON","value":{"code":400,"error":"invalid request body","success":false}},"invalid_mode":{"summary":"Unknown inbound mode","value":{"code":400,"error":"invalid call_inbound_mode: must be manual, bot, ivr, ai, webhook, or reject","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the configuration could not be saved to the database.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"pq: canceling statement due to user request","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/status":{"get":{"tags":["Call"],"summary":"List live calls","description":"Returns every call currently tracked by the native calls engine for this instance, inbound and outbound,\n1:1 and group, with its state, direction, media flags and start time.\n\n**Rules:**\n- Requires the engine to be running for the instance (**409** otherwise, including when the network route is mobile TCP-only).\n- Only live calls are listed; a call disappears as soon as it ends. An empty `calls` array means no call is in progress.\n- `state` is one of `idle`, `calling`, `ringing`, `connecting`, `active`, `ended` or `unknown`.\n- The order of the array is not stable.\n\n**Use Cases:**\n- Find the `callId` of an inbound call to answer it in manual mode\n- Show a live-calls panel in a dashboard\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Snapshot of the live calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStatusResponse"},"examples":{"two_calls":{"summary":"One active and one ringing call","value":{"code":200,"data":{"calls":[{"callId":"call_17B3F2A1C9D04E8F","peer":"123456789012345@lid","state":"active","direction":"inbound","video":false,"recording":true,"startedAt":"2026-09-15T14:21:08.412Z"},{"callId":"call_22A9E1B7D3F84C10","peer":"123456789012346@lid","state":"ringing","direction":"outbound","video":true,"recording":false,"startedAt":"2026-09-15T14:22:55.090Z"}]},"success":true}},"no_calls":{"summary":"No call in progress","value":{"code":200,"data":{"calls":[]},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/dial":{"post":{"tags":["Call"],"summary":"Place an outbound 1:1 call","description":"Places an outbound voice or video call to one person with the native calls engine (WebRTC with Opus audio\nand H.264 video) and returns the engine `callId` used by every other control endpoint and stream.\n\n**Target formats:**\n- Digits with country code and no `+` (for example `5511988888888`): resolved to the callee's LID before dialing.\n- Phone JID (`5511988888888@s.whatsapp.net`) or LID (`123456789012345@lid`): anything containing `@` is used as given.\n\n**Rules:**\n- `phone` is required; `video: true` offers H.264 video, otherwise the call is voice only.\n- A plain number is resolved first because the typed number is not always the canonical one (many Brazilian mobiles are stored without the ninth digit). If the lookup fails, dialing is still attempted with the input.\n- A group JID (`@g.us`) is not a valid target; use `/call/group/dial-by-id` or `/call/group/dial`.\n- Works in every inbound mode except `reject` (which keeps the engine off) once the engine is running; **409** otherwise.\n- The call's lifecycle is reported by the `call.offer`, `call.accept` and `call.terminate` webhooks; with `callRecord` on, the call is recorded once connected.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDialRequest"},"examples":{"voice_call":{"summary":"Voice call to a phone number","description":"The number is resolved to the callee's LID before the offer is sent.","value":{"phone":"5511988888888"}},"video_call":{"summary":"Video call to a phone number","description":"Same resolution as a voice call, with H.264 video offered.","value":{"phone":"5511988888888","video":true}},"voice_call_lid":{"summary":"Voice call to a LID","description":"A value containing `@` skips the number lookup and is used exactly as given.","value":{"phone":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"Outbound call placed; `data.callId` identifies it in every other call endpoint.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdResponse"},"example":{"code":200,"data":{"callId":"call_22A9E1B7D3F84C10"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `phone` is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"phone is required","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine could not place the call. Every dial failure maps here, including an unknown number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_lid":{"summary":"Number not on WhatsApp","value":{"code":502,"error":"usync returned no LID for 5511988888888 (peer unreachable or not on WhatsApp)","success":false}},"no_devices":{"summary":"Peer has no reachable device","value":{"code":502,"error":"peer 123456789012345@lid has no devices (unreachable / not on WhatsApp)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/answer":{"post":{"tags":["Call"],"summary":"Answer a ringing inbound call","description":"Answers an inbound call tracked by the native calls engine and starts its media session. Meant for\n`callInboundMode: manual`, where calls ring until the application decides; in `webhook` mode the engine\nanswers by itself.\n\n**Rules:**\n- `callId` is the engine call ID from `GET /call/status` or the `call.offer` webhook, not the WhatsApp signaling `call_id`.\n- **404** when no live call has that ID (already ended, or it belongs to another instance).\n- Engine refusals (for example the call is no longer ringing) are returned as **400** with the engine message.\n- After answering, attach media with `/call/{call_id}/stream`, `/call/play` or `/call/record/start`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdRequest"},"examples":{"answer":{"summary":"Answer a ringing call","description":"Answers the inbound call listed by `GET /call/status`.","value":{"callId":"call_17B3F2A1C9D04E8F"}}}}}},"responses":{"200":{"description":"Call answered.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: `callId` is missing, or the engine refused to answer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"engine_refused":{"summary":"Engine refused the answer","value":{"code":400,"error":"meowcaller: call is not active","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/hangup":{"post":{"tags":["Call"],"summary":"Hang up a live call","description":"Ends a call tracked by the native calls engine, in either direction, and tears down its media session.\nAn active recording is finalized and uploaded as part of the call end.\n\n**Rules:**\n- `callId` is the engine call ID returned by `/call/dial`, `/call/group/dial*`, `/call/link/join` or listed by `GET /call/status`.\n- **404** when the call is not live anymore; hanging up twice returns **404** the second time.\n- Engine errors while ending the call are returned as **400**.\n- The `call.terminate` webhook (and `call.recording_ready`, when recording) follows asynchronously.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdRequest"},"examples":{"hangup":{"summary":"End a call","description":"Ends the call placed earlier with `/call/dial`.","value":{"callId":"call_22A9E1B7D3F84C10"}}}}}},"responses":{"200":{"description":"Hangup sent and media torn down.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: `callId` is missing, or the engine failed to end the call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"callId is required","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/play":{"post":{"tags":["Call"],"summary":"Play audio into a live call","description":"Plays an audio clip to the other side of a live call. The clip is fetched or decoded up front, then queued\non the call's player; the response returns as soon as playback is scheduled, not when it finishes.\n\n**Features:**\n- **Formats**: WAV, Ogg/Opus and MP3, detected from the file content (anything that is not WAV or Ogg is decoded as MP3).\n- **Resampling**: every clip is converted to the call's native 16 kHz mono.\n- **Sources**: a public URL (downloaded with a 30 s timeout, at most 64 MiB) or inline base64.\n\n**Rules:**\n- `callId` is required, plus one of `audioUrl` or `audioBase64`; when both are sent, `audioUrl` wins.\n- `audioBase64` is standard base64 without a `data:` prefix.\n- Download, decode and format errors are returned as **400** with the underlying message, before the call is looked up.\n- **404** when the call already ended or the ID belongs to another instance.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallPlayRequest"},"examples":{"play_url":{"summary":"Play an MP3 from a URL","description":"The file is downloaded by the gateway, decoded and resampled before playback starts.","value":{"callId":"call_17B3F2A1C9D04E8F","audioUrl":"https://cdn.example.com/audio/welcome-message.mp3"}},"play_base64":{"summary":"Play a short WAV sent inline","description":"Base64 of a WAV file (truncated here); the container is detected from the RIFF header.","value":{"callId":"call_17B3F2A1C9D04E8F","audioBase64":"UklGRiQAAABXQVZFZm10IBAAAAABAAEAgD4AAAB9AAACABAAZGF0YQAAAAA="}}}}}},"responses":{"200":{"description":"Playback scheduled on the call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: `callId` or the audio source is missing, the base64 is invalid, or the audio could not be downloaded or decoded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"missing_source":{"summary":"Neither audioUrl nor audioBase64","value":{"code":400,"error":"audioUrl or audioBase64 is required","success":false}},"invalid_base64":{"summary":"audioBase64 is not valid base64","value":{"code":400,"error":"invalid audioBase64","success":false}},"url_status":{"summary":"audioUrl answered with an error status","value":{"code":400,"error":"voip: audio url status 404","success":false}},"too_short":{"summary":"Audio payload shorter than 4 bytes","value":{"code":400,"error":"voip: audio payload too short","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/record/start":{"post":{"tags":["Call"],"summary":"Start recording a live call","description":"Starts recording the other party's audio of a live call to a WAV file. The audio is sent during the call\nto the instance's own S3 (5 MiB multipart parts plus private 30 s checkpoints) and is never written to local\ndisk. Stop it with `POST /call/record/stop`, or let the call end: the recording is then finalized and announced\nby the `CallRecordingReady` webhook (`call.recording_ready`).\n\n**Rules:**\n- Requires `callRecord: true` in `PUT /call/config` (applied immediately); otherwise **403** `call_recording_disabled` and nothing is recorded.\n- Requires object storage (S3) for the instance and room in the process recording memory quota\n  (`GLOBAL_CALL_RECORDING_MEMORY_QUOTA_MB`); otherwise **400** with the reason.\n- Only the peer's inbound audio is recorded, not the audio played into the call.\n- Recording and the `/call/{call_id}/stream` audio WebSocket share the call's single inbound audio sink, so they cannot run at the same time on one call.\n- Starting while a recording is already running is a no-op and still returns `ok: true`.\n- `callRecord: true` in `PUT /call/config` starts recording automatically for every connected call.\n- If S3 is unreachable during the call, audio is kept in memory up to 128 MiB per recording or the quota; then\n  the recording stops, the call continues, and `CallRecordingStopped` (`Reason`: `recording_limit` or\n  `recording_quota`) is emitted once. What was already recorded still ends in `CallRecordingReady`.\n- Deploys and restarts do not lose finished recordings. A sudden crash loses at most the last 30 s of audio.\n- Silence is not recorded: a phone sends no packets while its user is silent, and gaps over 2 s never reach\n  the recorder, so a recording can be shorter than the call. Limits (30 s, 5 MiB parts) count recorded audio.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdRequest"},"examples":{"start_recording":{"summary":"Record a live call","description":"Starts recording the peer audio of an active call.","value":{"callId":"call_17B3F2A1C9D04E8F"}}}}}},"responses":{"200":{"description":"Recording started (or was already running).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: `callId` is missing, S3 is not configured, the recording store is unavailable, or the recording memory quota is full.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"no_storage":{"summary":"S3 not configured","value":{"code":400,"error":"voip: recording requires object storage (S3) to be configured","success":false}},"spool_unavailable":{"summary":"Recording store unavailable (database not ready)","value":{"code":400,"error":"voip: durable recording spool is unavailable","success":false}},"spool_quota":{"summary":"Recording memory quota full (GLOBAL_CALL_RECORDING_MEMORY_QUOTA_MB)","value":{"code":400,"error":"voip: durable recording spool quota exceeded","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"description":"Forbidden: recording is not authorized for this instance (`callRecord` is off in `PUT /call/config`). Nothing is recorded.\n\n**Pela API pública:** A instância está atribuída a uma conta (ou Revenda) desativada no painel. Desativar ou reativar a conta reflete na API em até 30 s.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":403,"error":"call_recording_disabled","success":false}},"ACCOUNT_DEACTIVATED":{"summary":"Conta dona desativada","value":{"code":"ACCOUNT_DEACTIVATED","message":"A conta dona desta instância está desativada no painel."}}}}}},"404":{"description":"Not Found: no live call with this `callId` for this instance (or it ended while the recorder was starting).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/record/stop":{"post":{"tags":["Call"],"summary":"Stop recording and upload the file","description":"Stops the active recording of a live call, uploads the WAV to object storage and returns its media URL.\nThe call itself keeps running. The `call.recording_ready` webhook is emitted for the uploaded file.\n\n**Rules:**\n- `mediaKey` holds the **URL** of the uploaded recording (the field name is historical).\n- When no recording is active, the response is still **200** with `mediaKey` as an empty string.\n- Upload failures are returned as **400** with the reason. The recording stays pending in the database and is\n  completed in the background when S3 answers (also by another instance after a deploy); `CallRecordingReady`\n  announces the file. A client that gets a 400 here should wait for that webhook instead of retrying stop.\n- Calling stop while the same recording is already being finalized (for example by the call ending) returns **400**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdRequest"},"examples":{"stop_recording":{"summary":"Stop recording and upload","description":"Finalizes the WAV of the running recording and uploads it to S3.","value":{"callId":"call_17B3F2A1C9D04E8F"}}}}}},"responses":{"200":{"description":"Recording finalized; `data.mediaKey` is the uploaded file URL, or empty when nothing was recording.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallRecordingStopResponse"},"examples":{"uploaded":{"summary":"Recording uploaded","value":{"code":200,"data":{"ok":true,"mediaKey":"https://my-bucket.s3.amazonaws.com/call-recordings/9b2f6a1e-4c1d-4e0b-8f7a-2d3c4b5a6e7f.wav"},"success":true}},"not_recording":{"summary":"No active recording","value":{"code":200,"data":{"ok":true,"mediaKey":""},"success":true}}}}}},"400":{"description":"Bad Request: `callId` is missing, or the recording could not be finalized or uploaded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"already_finalizing":{"summary":"Recording already being finalized","value":{"code":400,"error":"recording is already being finalized","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/group/dial":{"post":{"tags":["Call"],"summary":"Place a group call to a list of people","description":"Places an outbound group call to an explicit list of people with the native calls engine and returns its\n`callId`. Optionally binds the call to an existing WhatsApp group while ringing only some of its members.\n\n**Features:**\n- **Ad-hoc group call**: ring 2 to 31 people who do not need to share a group.\n- **Group-bound subset**: with `groupJid`, the call belongs to that group but only `targets` are rung. This is the only way to call a group larger than WhatsApp's limit of 32 connected participants, which `/call/group/dial-by-id` refuses.\n- **Video**: `video: true` offers H.264 video to every participant.\n\n**Rules:**\n- `targets` needs at least two entries (**400** otherwise); each is a phone number, phone JID or LID.\n- The engine discards duplicates and this account itself; more than 31 remote targets, or fewer than two distinct ones after that, fails with **502** and the engine message.\n- Any failure while resolving targets or sending the offer is **502**; a refusal by WhatsApp includes its error code (`whatsapp refused the call request (error N)`).\n- The call is listed by `GET /call/status` and emits the same call webhooks as a 1:1 call.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallGroupDialRequest"},"examples":{"voice_group":{"summary":"Voice group call to three people","description":"An ad-hoc call; the targets do not need to share a WhatsApp group.","value":{"targets":["5511988888888","5511977777777","123456789012345@lid"]}},"video_group":{"summary":"Video group call","description":"Same as a voice group call, with H.264 video offered.","value":{"targets":["5511988888888@s.whatsapp.net","5511977777777@s.whatsapp.net"],"video":true}},"bound_subset":{"summary":"Call part of a large group","description":"The call belongs to the group, but only the listed members are rung.","value":{"groupJid":"120363000000000011@g.us","targets":["5511988888888","5511977777777"]}}}}}},"responses":{"200":{"description":"Group call placed; `data.callId` identifies it in the other call endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdResponse"},"example":{"code":200,"data":{"callId":"call_5C1E9A7B3D2F4E60"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `targets` has fewer than two entries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"targets is required and needs at least two entries","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine could not place the group call, or WhatsApp refused it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"too_many_targets":{"summary":"More than 31 remote targets","value":{"code":502,"error":"meowcaller: group call supports at most 31 remote targets","success":false}},"unreachable_participant":{"summary":"A target has no reachable device","value":{"code":502,"error":"meowcaller: participant 123456789012345@lid has no reachable devices","success":false}},"refused":{"summary":"WhatsApp refused the call","value":{"code":502,"error":"whatsapp refused the call request (error 431)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/group/dial-by-id":{"post":{"tags":["Call"],"summary":"Place a group call to every member of a WhatsApp group","description":"Places an outbound group call bound to an existing WhatsApp group: the engine reads the group roster and\nrings every other member. No target list is needed.\n\n**Rules:**\n- `groupJid` is required and must be a group this account belongs to (`...@g.us`).\n- The group needs 2 to 31 other members. Larger groups are refused; call a subset with `POST /call/group/dial` and `groupJid` instead.\n- Resolution, size and signaling failures are **502** with the engine or WhatsApp message.\n- `video: true` offers H.264 video.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallGroupDialByIDRequest"},"examples":{"voice_group":{"summary":"Voice call to a whole group","description":"Every member of the group except this account is rung.","value":{"groupJid":"120363000000000011@g.us"}},"video_group":{"summary":"Video call to a whole group","description":"Same as the voice call, with H.264 video offered.","value":{"groupJid":"120363000000000011@g.us","video":true}}}}}},"responses":{"200":{"description":"Group call placed; `data.callId` identifies it in the other call endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdResponse"},"example":{"code":200,"data":{"callId":"call_5C1E9A7B3D2F4E60"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `groupJid` is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"groupJid is required","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the group roster could not be used for a call, or WhatsApp refused it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"too_many_members":{"summary":"Group larger than the call limit","value":{"code":502,"error":"meowcaller: group call by ID has 45 remote members; at most 31 can be called","success":false}},"too_few_members":{"summary":"Group with fewer than two other members","value":{"code":502,"error":"meowcaller: group call by ID requires at least two remote members","success":false}},"refused":{"summary":"WhatsApp refused the call","value":{"code":502,"error":"whatsapp refused the call request (error 431)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/participants/add":{"post":{"tags":["Call"],"summary":"Invite people into a live call","description":"Invites one or more people into a call that is already established. Each target is invited independently,\nso one failure does not stop the others and the response lists exactly which targets failed.\n\n**Rules:**\n- `callId` and a non-empty `targets` array are required; each target is a phone number, phone JID or LID.\n- The HTTP status is **200** even when some or all invites fail: check `data.ok` and `data.failed` (entries are `\"<target>: <reason>\"`).\n- Inviting someone already in the roster, or this account itself, is reported in `failed`.\n- An unknown or already-ended `callId` answers **404**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallParticipantsAddRequest"},"examples":{"add_one":{"summary":"Invite one person","description":"Adds one phone number to an established call.","value":{"callId":"call_5C1E9A7B3D2F4E60","targets":["5511966666666"]}},"add_several":{"summary":"Invite several people","description":"Every target is invited on its own; failures are reported per target.","value":{"callId":"call_5C1E9A7B3D2F4E60","targets":["5511966666666","123456789012347@lid"]}}}}}},"responses":{"200":{"description":"Invites processed. `data.ok` is false when at least one target failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallParticipantsAddResponse"},"examples":{"all_invited":{"summary":"Every target invited","value":{"code":200,"data":{"ok":true,"failed":[]},"success":true}},"partial_failure":{"summary":"One target failed","value":{"code":200,"data":{"ok":false,"failed":["123456789012347@lid: meowcaller: participant is already in the call roster"]},"success":true}}}}}},"400":{"description":"Bad Request: the body is not valid JSON, or `callId`/`targets` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"callId and targets are required","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/participants/ring":{"post":{"tags":["Call"],"summary":"Ring a participant again","description":"Rings again a participant who is already on the roster of a live group call but is not connected, for\nexample someone who missed or declined the first ring.\n\n**Rules:**\n- `callId` and `target` are required strings; `target` is a phone number, phone JID or LID.\n- The target must be in the call roster and not connected; otherwise the engine refuses with **502** (`participant is not in the call roster`, `participant is already connected`).\n- To bring in someone new, use `POST /call/participants/add`.\n- **404** when the group call is no longer tracked.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallParticipantRingRequest"},"examples":{"ring_again":{"summary":"Ring a member who did not answer","description":"The target is on the roster of the group call but not connected.","value":{"callId":"call_5C1E9A7B3D2F4E60","target":"5511977777777"}}}}}},"responses":{"200":{"description":"Ring sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object of strings, or `callId`/`target` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object of strings","value":{"code":400,"error":"invalid payload","success":false}},"missing_fields":{"summary":"callId or target missing","value":{"code":400,"error":"callId and target are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine or WhatsApp refused to ring the participant.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"not_in_roster":{"summary":"Target is not on the roster","value":{"code":502,"error":"meowcaller: participant is not in the call roster","success":false}},"already_connected":{"summary":"Target is already connected","value":{"code":502,"error":"meowcaller: participant is already connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/link/create":{"post":{"tags":["Call"],"summary":"Create a WhatsApp call link","description":"Creates a reusable public call link (`https://call.whatsapp.com/audio/...` or `/video/...`). Anyone with the\nlink can join the call, subject to the waiting room when approval is required.\n\n**Rules:**\n- The body is optional: an empty or missing body creates a voice link; `video: true` creates a video link.\n- Creating a link does not start a call; join it with `POST /call/link/join` to be in the call.\n- Signaling failures are **502** with the engine message.\n- Requires the native calls engine (**409** otherwise).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallLinkCreateRequest"},"examples":{"voice_link":{"summary":"Create a voice call link","description":"Equivalent to sending no body.","value":{"video":false}},"video_link":{"summary":"Create a video call link","description":"The returned URL uses the `/video/` path.","value":{"video":true}}}}}},"responses":{"200":{"description":"Call link created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallLinkCreateResponse"},"example":{"code":200,"data":{"token":"Xk3pQ9aB7cD2eF4g","url":"https://call.whatsapp.com/video/Xk3pQ9aB7cD2eF4g","video":true},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: WhatsApp did not create the link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"signaling_unavailable":{"summary":"Call-link signaling unavailable","value":{"code":502,"error":"meowcaller: call-link signaling is unavailable","success":false}},"no_token":{"summary":"WhatsApp answered without a token","value":{"code":502,"error":"meowcaller: create call link returned no token","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/link/preview":{"get":{"tags":["Call"],"summary":"Preview a call link without joining","description":"Reads the metadata of a WhatsApp call link (media type, whether approval is required, whether this account\nis an admin, and the creator) without joining the call.\n\n**Rules:**\n- The query parameter `token` is the **call-link** token or full URL, not the API token. Authenticate with the `token` **header** here: a query `token` is read as the call-link value and a request without the header answers **401**.\n- A full URL must be `https://call.whatsapp.com/audio/<token>` or `/video/<token>`; anything else fails with **502** `invalid WhatsApp call-link URL`.\n- `video=true` (exactly `true`) previews it as a video link; any other value means voice.\n- `creator` and `creatorPhone` are omitted when WhatsApp does not disclose them.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"token","in":"query","required":true,"description":"Call-link token or full `https://call.whatsapp.com/...` URL. Not the API authentication token.","schema":{"type":"string"},"example":"https://call.whatsapp.com/video/Xk3pQ9aB7cD2eF4g"},{"name":"video","in":"query","required":false,"description":"`true` previews the link as a video link; any other value is voice.","schema":{"type":"boolean","default":false},"example":true}],"responses":{"200":{"description":"Call-link metadata.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallLinkPreviewResponse"},"example":{"code":200,"data":{"token":"Xk3pQ9aB7cD2eF4g","video":true,"approvalRequired":true,"isAdmin":false,"creator":"123456789012345@lid","creatorPhone":"5511988888888@s.whatsapp.net"},"success":true}}}},"400":{"description":"Bad Request: the `token` query parameter is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"token is required","success":false}}}},"401":{"description":"Missing or invalid user token. On this route the API token must be sent in the `token` header.\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the link is malformed or WhatsApp could not resolve it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_url":{"summary":"Not a WhatsApp call-link URL","value":{"code":502,"error":"meowcaller: invalid WhatsApp call-link URL","success":false}},"no_result":{"summary":"WhatsApp returned no preview","value":{"code":502,"error":"meowcaller: preview call link returned no result","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/link/join":{"post":{"tags":["Call"],"summary":"Join a call link","description":"Joins the call behind a WhatsApp call link, or enters its waiting room when the link requires approval. The\nresulting call is tracked like any other, so `/call/status`, the streams and `/call/hangup` work with the\nreturned `callId`.\n\n**Rules:**\n- `token` is required and accepts the bare call-link token or the full `https://call.whatsapp.com/audio|video/<token>` URL.\n- When approval is required, the call stays in the waiting room until an admin admits this account; follow it with `GET /call/{call_id}/waiting-room` or the `/call/{call_id}/events` stream.\n- Malformed links and WhatsApp refusals are **502**.\n- `video: true` joins with video.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallLinkJoinRequest"},"examples":{"join_with_token":{"summary":"Join with the bare token","description":"Joins as a voice participant.","value":{"token":"Xk3pQ9aB7cD2eF4g"}},"join_with_url":{"summary":"Join a video link by URL","description":"The token is extracted from the URL; `video` joins with the camera track.","value":{"token":"https://call.whatsapp.com/video/Xk3pQ9aB7cD2eF4g","video":true}}}}}},"responses":{"200":{"description":"Joined (or waiting for approval); `data.callId` identifies the call.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallIdResponse"},"example":{"code":200,"data":{"callId":"call_8D4B2E6A1C9F3E70"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `token` is empty.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"token is required","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the link is malformed, or WhatsApp refused the join.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_token":{"summary":"Token contains a slash but is not a URL","value":{"code":502,"error":"meowcaller: invalid call-link token","success":false}},"refused":{"summary":"WhatsApp refused the join","value":{"code":502,"error":"whatsapp refused the call request (error 431)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/waiting-room/admit":{"post":{"tags":["Call"],"summary":"Admit a user from the call-link waiting room","description":"Lets one user who is waiting for approval into a call-link call. Only an admin of the call link can admit.\n\n**Rules:**\n- `callId` and `user` are required strings; `user` is the waiting user's JID as listed by `GET /call/{call_id}/waiting-room`.\n- Refusals (not an admin, user no longer waiting, no waiting room) come back as **502** with the WhatsApp or engine message.\n- A body whose values are not strings is rejected with **400** `invalid payload`.\n- **404** when the call-link call has already ended.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallWaitingRoomUserRequest"},"examples":{"admit_user":{"summary":"Admit a waiting user","description":"Uses a JID taken from the waiting-room roster.","value":{"callId":"call_8D4B2E6A1C9F3E70","user":"123456789012345@lid"}}}}}},"responses":{"200":{"description":"User admitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object of strings, or `callId`/`user` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object of strings","value":{"code":400,"error":"invalid payload","success":false}},"missing_fields":{"summary":"callId or user missing","value":{"code":400,"error":"callId and user are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: WhatsApp or the engine refused to admit the user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"whatsapp refused the call request (error 431)","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/waiting-room/deny":{"post":{"tags":["Call"],"summary":"Deny a user in the call-link waiting room","description":"Rejects one user who is waiting for approval to join a call-link call; the user does not enter the call.\nOnly an admin of the call link can deny.\n\n**Rules:**\n- `callId` and `user` are required strings; take `user` from `GET /call/{call_id}/waiting-room` or the `waiting-room` event.\n- WhatsApp or engine refusals are **502**; a live call that is no longer tracked is **404**.\n- Denying does not block the user from asking to join again.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallWaitingRoomUserRequest"},"examples":{"deny_user":{"summary":"Deny a waiting user","description":"Uses a JID taken from the waiting-room roster.","value":{"callId":"call_8D4B2E6A1C9F3E70","user":"123456789012346@lid"}}}}}},"responses":{"200":{"description":"User denied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object of strings, or `callId`/`user` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object of strings","value":{"code":400,"error":"invalid payload","success":false}},"missing_fields":{"summary":"callId or user missing","value":{"code":400,"error":"callId and user are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: WhatsApp or the engine refused to deny the user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"whatsapp refused the call request (error 431)","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/waiting-room/approval":{"post":{"tags":["Call"],"summary":"Turn call-link approval on or off","description":"Turns the waiting room of a call-link call on or off. With approval on, new joiners wait until an admin\nadmits them; with approval off, they join directly. Only an admin of the call link can change it.\n\n**Rules:**\n- `callId` is required. `enabled` defaults to `true` when omitted and must be a JSON boolean (**400** for `\"true\"` as a string).\n- The response echoes the applied value in `data.enabled`.\n- Refusals by WhatsApp (for example not an admin) are **502**; an untracked call is **404**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallApprovalRequest"},"examples":{"require_approval":{"summary":"Require approval to join","description":"New joiners go to the waiting room.","value":{"callId":"call_8D4B2E6A1C9F3E70","enabled":true}},"open_link":{"summary":"Let anyone with the link join directly","description":"Disables the waiting room.","value":{"callId":"call_8D4B2E6A1C9F3E70","enabled":false}},"default_true":{"summary":"Omit enabled","description":"Without `enabled` the handler applies `true`.","value":{"callId":"call_8D4B2E6A1C9F3E70"}}}}}},"responses":{"200":{"description":"Approval setting applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEnabledToggleResponse"},"example":{"code":200,"data":{"ok":true,"enabled":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `callId` is missing, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid payload","success":false}},"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"not_boolean":{"summary":"enabled is not a boolean","value":{"code":400,"error":"enabled must be a boolean","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: WhatsApp refused the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"whatsapp refused the call request (error 431)","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/reaction":{"post":{"tags":["Call"],"summary":"Send an emoji reaction inside a live call","description":"Shows an emoji reaction to everyone in a live call, like the reaction bar of the official apps. Reactions\nare transient: other participants see them briefly and they are not stored.\n\n**Rules:**\n- `callId` and `emoji` are required strings; an empty `emoji` is rejected, so a reaction cannot be cleared through this route.\n- The emoji must be valid UTF-8; engine errors (for example the call has no media yet) are **502**.\n- Reactions from other participants arrive as `reaction` events on `GET /call/{call_id}/events`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallReactionRequest"},"examples":{"thumbs_up":{"summary":"React with a thumbs up","description":"Sends a thumbs-up to every participant.","value":{"callId":"call_5C1E9A7B3D2F4E60","emoji":"👍"}},"heart":{"summary":"React with a heart","description":"Any single emoji works the same way.","value":{"callId":"call_5C1E9A7B3D2F4E60","emoji":"❤️"}}}}}},"responses":{"200":{"description":"Reaction sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallOkResponse"},"example":{"code":200,"data":{"ok":true},"success":true}}}},"400":{"description":"Bad Request: the body is not a JSON object of strings, or `callId`/`emoji` is missing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object of strings","value":{"code":400,"error":"invalid payload","success":false}},"missing_fields":{"summary":"callId or emoji missing","value":{"code":400,"error":"callId and emoji are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine could not send the reaction.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"meowcaller: call is not active","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/hand":{"post":{"tags":["Call"],"summary":"Raise or lower your hand in a live call","description":"Raises or lowers this account's hand in a live call. The state is persistent: it stays visible to the\nother participants until it is lowered again.\n\n**Rules:**\n- `callId` is required. `raised` defaults to `true` when omitted and must be a JSON boolean.\n- The applied value is echoed in `data.raised`.\n- Other participants' hand changes arrive as `hand` events on `GET /call/{call_id}/events`.\n- Engine errors are **502**; an untracked call is **404**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallHandRequest"},"examples":{"raise_hand":{"summary":"Raise your hand","description":"Shows the raised-hand indicator to the other participants.","value":{"callId":"call_5C1E9A7B3D2F4E60","raised":true}},"lower_hand":{"summary":"Lower your hand","description":"Removes the raised-hand indicator.","value":{"callId":"call_5C1E9A7B3D2F4E60","raised":false}},"default_true":{"summary":"Omit raised","description":"Without `raised` the handler raises the hand.","value":{"callId":"call_5C1E9A7B3D2F4E60"}}}}}},"responses":{"200":{"description":"Hand state applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallHandResponse"},"example":{"code":200,"data":{"ok":true,"raised":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `callId` is missing, or `raised` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid payload","success":false}},"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"not_boolean":{"summary":"raised is not a boolean","value":{"code":400,"error":"raised must be a boolean","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine could not change the hand state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"meowcaller: call is not active","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/video":{"post":{"tags":["Call"],"summary":"Start or stop sending your video in a live call","description":"Starts or stops this account's outbound video track in a live call, for example to upgrade a voice call to\nvideo. The picture itself is sent as H.264 access units through `GET /call/{call_id}/video/stream`.\n\n**Rules:**\n- `callId` is required. `enabled` defaults to `true` and must be a JSON boolean.\n- `enabled: true` requests a voice-to-video upgrade; outbound video only flows after the other side accepts it.\n- `enabled: false` stops the outbound video while the peer's video and the audio keep flowing.\n- Engine refusals (for example the call is not active) are **502**; an untracked call is **404**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallVideoToggleRequest"},"examples":{"start_video":{"summary":"Turn your camera on","description":"Requests the upgrade to video for this call.","value":{"callId":"call_17B3F2A1C9D04E8F","enabled":true}},"stop_video":{"summary":"Turn your camera off","description":"Stops the outbound video track only.","value":{"callId":"call_17B3F2A1C9D04E8F","enabled":false}},"default_true":{"summary":"Omit enabled","description":"Without `enabled` the handler turns video on.","value":{"callId":"call_17B3F2A1C9D04E8F"}}}}}},"responses":{"200":{"description":"Video state change requested.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEnabledToggleResponse"},"example":{"code":200,"data":{"ok":true,"enabled":true},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `callId` is missing, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid payload","success":false}},"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"not_boolean":{"summary":"enabled is not a boolean","value":{"code":400,"error":"enabled must be a boolean","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine could not change the video state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"meowcaller: call is not active","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/screenshare":{"post":{"tags":["Call"],"summary":"Start or stop screen sharing in a live call","description":"Announces to the other participants that this account started or stopped sharing its screen. The screen\nshare state is independent from the camera state set with `POST /call/video`.\n\n**Rules:**\n- `callId` is required. `enabled` defaults to `true` when omitted and must be a JSON boolean.\n- The frames themselves are pushed through `GET /call/{call_id}/video/stream`; this route only changes the announced state.\n- Other participants' screen-share changes arrive as `screenshare` events on `GET /call/{call_id}/events`.\n- Engine errors are **502**; an untracked call is **404**.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallScreenShareRequest"},"examples":{"start_screenshare":{"summary":"Start sharing the screen","description":"Announces a screen share to the other participants.","value":{"callId":"call_5C1E9A7B3D2F4E60","enabled":true}},"stop_screenshare":{"summary":"Stop sharing the screen","description":"Announces that the screen share ended.","value":{"callId":"call_5C1E9A7B3D2F4E60","enabled":false}},"default_true":{"summary":"Omit enabled","description":"Without `enabled` the handler starts the screen share.","value":{"callId":"call_5C1E9A7B3D2F4E60"}}}}}},"responses":{"200":{"description":"Screen-share state applied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEnabledToggleResponse"},"example":{"code":200,"data":{"ok":true,"enabled":false},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `callId` is missing, or `enabled` is not a boolean.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payload":{"summary":"Body is not a JSON object","value":{"code":400,"error":"invalid payload","success":false}},"missing_call_id":{"summary":"callId missing","value":{"code":400,"error":"callId is required","success":false}},"not_boolean":{"summary":"enabled is not a boolean","value":{"code":400,"error":"enabled must be a boolean","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this `callId` for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"502":{"description":"Bad Gateway: the engine could not change the screen-share state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"meowcaller: call is not active","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/{call_id}/stream":{"get":{"tags":["Call"],"summary":"Bidirectional raw PCM audio WebSocket for a live call","description":"**Não suportado pela URL base pública:** este stream WebSocket não é repassado pelo proxy da API; a chamada responde `501` com `code` `WEBSOCKET_NOT_SUPPORTED`.\n\nUpgrades to a WebSocket that bridges raw PCM audio with a live call: the other party's audio is pushed to\nthe client, and audio the client sends is played to the other party. This is how a custom media\napplication (speech bot, recorder, softphone) connects to a call answered with the native calls engine.\n\n**Wire format:**\n- Server to client: binary messages of signed 16-bit little-endian PCM, 16 kHz, mono; one message per 60 ms frame (960 samples, 1920 bytes).\n- Client to server: binary messages with the same PCM format, any length up to 64 KiB; they are split into 60 ms frames and played in order (the last partial frame is zero-padded). Text messages are ignored.\n- Frames that arrive faster than they can be played are dropped once 128 frames are queued.\n\n**Rules:**\n- Authenticate with the header `token` or, from a browser `WebSocket`, the query string `?token=`.\n- The engine and the call are checked **before** the upgrade, so **409** and **404** arrive as JSON envelopes; a request that is not a WebSocket upgrade gets a plain-text **400**.\n- The server pings every 20 s; a client that neither answers pings nor sends data for 60 s is disconnected. A write blocked for 5 s also closes the socket.\n- The socket and call recording share the call's single inbound audio sink, so they cannot run at the same time on one call.\n- Closing the socket stops the playback fed by it; the call itself keeps running.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of the live call (from `/call/dial` or `GET /call/status`).","schema":{"type":"string"},"example":"call_17B3F2A1C9D04E8F"}],"responses":{"101":{"description":"Switching Protocols: the WebSocket is open and PCM frames start flowing."},"400":{"description":"Bad Request: the request is not a valid WebSocket upgrade. Written by the WebSocket library as plain text.","content":{"text/plain":{"schema":{"type":"string","description":"HTTP status text.","example":"Bad Request"},"example":"Bad Request"}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":401,"error":"unauthorized","success":false}}}},"404":{"description":"Not Found: no live call with this ID for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"501":{"$ref":"#/components/responses/PublicApiWebSocketNotSupported"}}}},"/call/{call_id}/video/stream":{"get":{"tags":["Call"],"summary":"Bidirectional H.264 video WebSocket for a live call","description":"**Não suportado pela URL base pública:** este stream WebSocket não é repassado pelo proxy da API; a chamada responde `501` com `code` `WEBSOCKET_NOT_SUPPORTED`.\n\nUpgrades to a WebSocket that carries encoded H.264 video for a live call. The gateway never encodes or\ndecodes pixels: the client consumes the other party's access units and produces its own.\n\n**Wire format:**\n- Client to server (binary): one H.264 Annex-B access unit per message, at most 1 MiB. The first access unit WhatsApp accepts announces the local camera as on; closing the socket announces it as off.\n- Server to client, default framing (binary): bare Annex-B access units from every camera muxed into one stream. Only decodable while a single camera is on.\n- Server to client with `fmt=participant` (binary): `[1 byte version = 2][1 byte id length][participant id, UTF-8][Annex-B access unit]`, one decoder per participant. Required for group video.\n- Text messages carry JSON control events. Server to client: `participant` (new camera with `id`, `sender`, `device`, `ssrc`, optional `orientation`), `orientation` (rotation change), `video-ready` (outbound video media is live), `keyframe` (the peer asked for an IDR). Client to server: `{\"type\":\"hello\",\"fmt\":\"participant\"}` switches to participant framing; `{\"type\":\"client-log\",\"message\":\"...\"}` writes a diagnostic to the server log.\n\n**Rules:**\n- Authenticate with the header `token` or, from a browser `WebSocket`, the query string `?token=`.\n- **409** and **404** are returned as JSON before the upgrade; a request that is not a WebSocket upgrade gets a plain-text **400**.\n- Under backpressure the server sheds queued frames forward to the next keyframe instead of adding latency (8 frames per camera, 24 MiB per socket, 32 cameras).\n- Outbound frames sent before the call has video media are dropped silently; `GET /call/{call_id}/video/stats` shows the counters.\n- One socket per call: a reconnect replaces the previous socket, which stops receiving frames. Pings every 20 s, 60 s idle timeout, 20 s write timeout.\n- Use `POST /call/video` to start or stop the outbound video track itself.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of the live call.","schema":{"type":"string"},"example":"call_17B3F2A1C9D04E8F"},{"name":"fmt","in":"query","required":false,"description":"Inbound framing. `participant` tags every access unit with its participant (needed for group calls); any other value or absence keeps bare access units.","schema":{"type":"string","enum":["participant"]},"example":"participant"}],"responses":{"101":{"description":"Switching Protocols: the WebSocket is open; binary access units and JSON control events start flowing."},"400":{"description":"Bad Request: the request is not a valid WebSocket upgrade. Written by the WebSocket library as plain text.","content":{"text/plain":{"schema":{"type":"string","description":"HTTP status text.","example":"Bad Request"},"example":"Bad Request"}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":401,"error":"unauthorized","success":false}}}},"404":{"description":"Not Found: no live call with this ID for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"501":{"$ref":"#/components/responses/PublicApiWebSocketNotSupported"}}}},"/call/{call_id}/video/state":{"get":{"tags":["Call"],"summary":"Stream the peer's video state (Server-Sent Events)","description":"Opens a Server-Sent Events stream with the other party's video state for a live call: camera on or off,\na mid-call upgrade from voice to video, and device orientation for rendering the picture upright.\n\n**Event format:**\n- The stream starts with `retry: 3000` so `EventSource` reconnects after 3 s.\n- Each change is one `data:` line with a JSON object: `active` (camera on), `upgrade` (voice-to-video upgrade request), `raw` (unmapped WhatsApp state value) and `orientation` (0-3, rotate by orientation x 90 degrees). `orientation` is omitted when the peer reports a value outside 0-3.\n- A `: keepalive` comment is written every 15 s.\n\n**Rules:**\n- Authenticate with the header `token` or, from `EventSource`, the query string `?token=`.\n- **409** and **404** are returned as JSON before the stream starts; after that the response is always **200** with `text/event-stream`.\n- Several subscribers can listen to the same call; a slow subscriber misses events rather than delaying others.\n- There is no initial snapshot: the first event arrives on the next change.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of the live call.","schema":{"type":"string"},"example":"call_17B3F2A1C9D04E8F"}],"responses":{"200":{"description":"Event stream opened.","content":{"text/event-stream":{"schema":{"type":"string","description":"SSE stream; every `data:` line is a JSON video state object.","example":"retry: 3000\n\ndata: {\"active\":true,\"orientation\":0,\"raw\":1,\"upgrade\":false}\n\n"},"example":"retry: 3000\n\ndata: {\"active\":true,\"orientation\":0,\"raw\":1,\"upgrade\":false}\n\n: keepalive\n\ndata: {\"active\":false,\"raw\":0,\"upgrade\":false}\n\n"}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this ID for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/{call_id}/video/stats":{"get":{"tags":["Call"],"summary":"Get live video telemetry for a call","description":"Returns counters of the video WebSocket attached to a live call while it runs: cameras received, frames\nreceived versus delivered and shed under backpressure, backlog size, and the outbound pipeline. Use it to\ntell server-side backpressure apart from client-side decoding lag.\n\n**Rules:**\n- Only available while a `/call/{call_id}/video/stream` socket is connected; otherwise **404** `no live video stream for this call`.\n- A call ID of another instance also answers **404**, exactly like a call without a video socket.\n- Rates (`framesPerSecond`) are averages since the socket opened, not instantaneous values.\n- `outbound.mediaReadyAfterSeconds` only appears once the first outbound frame was accepted.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of a live call with a connected video socket.","schema":{"type":"string"},"example":"call_17B3F2A1C9D04E8F"}],"responses":{"200":{"description":"Current video telemetry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallVideoStatsResponse"},"example":{"code":200,"data":{"callId":"call_17B3F2A1C9D04E8F","framing":"participant","uptimeSeconds":42.7,"inbound":{"participants":1,"framesReceived":1260,"framesDelivered":1248,"framesShed":12,"participantsRejected":0,"backlogBytes":0,"peakBacklogBytes":184320,"participantCap":32,"framesPerSecond":29.2,"streams":[{"id":"123456789012345@lid","frames":1260,"bytes":5120344,"orientation":0,"ssrc":3405691582,"secondsSinceLastFrame":0.03,"secondsActive":42.1,"fps":29.9}]},"outbound":{"framesSent":1190,"bytesSent":4388120,"framesDropped":35,"framesOversize":0,"keyframeRequests":2,"mediaReady":true,"mediaReadyAfterSeconds":1.8,"framesPerSecond":27.9}},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: the call is not live for this instance, or no video socket is connected to it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"no live video stream for this call","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/{call_id}/events":{"get":{"tags":["Call"],"summary":"Stream in-call events (Server-Sent Events)","description":"Opens a Server-Sent Events stream with everything that happens inside a live call: reactions, raised hands,\nscreen sharing, mute state, group roster and waiting-room changes, and call phase transitions. Reactions\nexist only as events (there is nothing to poll), which is why this is a stream.\n\n**Event format:**\n- The stream starts with `retry: 3000`, then one `data:` line per event with a JSON object carrying `seq` and `type`.\n- `reaction`: `emoji`, `participant`, `participantId`, `device`, `removed` (true when the reaction was withdrawn).\n- `hand`: `participant`, `raised`. `screenshare`: `participant`, `active`.\n- `mute`: `muted`; it reports this account's own mute state and carries no participant.\n- `group-state` and `waiting-room`: `state` holds the engine roster object verbatim (Go field names such as `TransactionID` and `Participants`).\n- `phase`: `phase` is `idle`, `calling`, `ringing`, `connecting`, `active`, `ended` or `unknown`.\n- A `: keepalive` comment is written every 15 s.\n\n**Rules:**\n- Authenticate with the header `token` or, from `EventSource`, the query string `?token=`.\n- On connect, the last known mute, hand and screen-share states are replayed first with `seq: 0`; live events then use an increasing `seq` shared by all subscribers of the call.\n- The first subscriber also receives the cached group roster and waiting room right away, when the call has them.\n- A subscriber that falls 64 events behind misses events instead of slowing the call down.\n- **409** and **404** are JSON responses sent before the stream starts; **500** `streaming unsupported` when the connection cannot be flushed.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of the live call.","schema":{"type":"string"},"example":"call_17B3F2A1C9D04E8F"}],"responses":{"200":{"description":"Event stream opened.","content":{"text/event-stream":{"schema":{"type":"string","description":"SSE stream; every `data:` line is a JSON call event.","example":"retry: 3000\n\ndata: {\"seq\":1,\"type\":\"phase\",\"phase\":\"active\"}\n\n"},"example":"retry: 3000\n\ndata: {\"seq\":0,\"type\":\"hand\",\"participant\":\"123456789012345@lid\",\"raised\":true}\n\ndata: {\"seq\":7,\"type\":\"reaction\",\"participant\":\"123456789012346@lid\",\"participantId\":\"2\",\"emoji\":\"👍\"}\n\ndata: {\"seq\":8,\"type\":\"phase\",\"phase\":\"ended\"}\n\n"}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this ID for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the native calls engine is not running for this instance, or the network route blocks calls.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the HTTP connection does not support streaming (for example behind a buffering proxy).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"streaming unsupported","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/{call_id}/group/state":{"get":{"tags":["Call"],"summary":"Get the roster of a live group call","description":"Returns the authoritative participant roster WhatsApp reported for a live group call: who is in it, the\nphone number when known, and each participant's state.\n\n**Rules:**\n- Only group calls have a roster: a 1:1 call answers **409** `this call has no group roster`.\n- `state` is the raw WhatsApp roster state, for example `connected`, `outgoing`, `receipt` or `invited`.\n- `phone` is omitted when WhatsApp did not provide the phone number for a LID participant.\n- For push updates instead of polling, listen to `group-state` events on `GET /call/{call_id}/events`.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of a live group call.","schema":{"type":"string"},"example":"call_5C1E9A7B3D2F4E60"}],"responses":{"200":{"description":"Current group roster.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallGroupStateResponse"},"example":{"code":200,"data":{"callId":"call_5C1E9A7B3D2F4E60","transactionId":4,"participants":[{"jid":"123456789012340@lid","state":"connected"},{"jid":"123456789012345@lid","phone":"5511988888888@s.whatsapp.net","state":"connected"},{"jid":"123456789012346@lid","phone":"5511977777777@s.whatsapp.net","state":"outgoing"}]},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this ID for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the engine is not running (or the network route blocks calls), or the call has no group roster.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_roster":{"summary":"1:1 call without a group roster","value":{"code":409,"error":"voip: not available for this call: this call has no group roster","success":false}},"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/call/{call_id}/waiting-room":{"get":{"tags":["Call"],"summary":"Get the waiting room of a call-link call","description":"Returns the waiting-room state of a live call-link call: whether approval is on, whether this account is an\nadmin or is itself waiting, and the users waiting for admission.\n\n**Rules:**\n- Only call-link calls have a waiting room: other calls answer **409** `this call has no waiting room`.\n- Admit or deny the listed `users` with `POST /call/waiting-room/admit` and `/call/waiting-room/deny` (admins only).\n- `inWaitingRoom: true` means this account joined a link and is still waiting to be admitted.\n- For push updates, listen to `waiting-room` events on `GET /call/{call_id}/events`.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"description":"Engine call ID of a live call-link call.","schema":{"type":"string"},"example":"call_8D4B2E6A1C9F3E70"}],"responses":{"200":{"description":"Current waiting-room state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallWaitingRoomResponse"},"example":{"code":200,"data":{"callId":"call_8D4B2E6A1C9F3E70","enabled":true,"isAdmin":true,"inWaitingRoom":false,"transactionId":2,"users":[{"jid":"123456789012346@lid","phone":"5511977777777@s.whatsapp.net"}]},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: no live call with this ID for this instance.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"call not found","success":false}}}},"409":{"description":"Conflict: the engine is not running (or the network route blocks calls), or the call has no waiting room.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_waiting_room":{"summary":"Call without a waiting room","value":{"code":409,"error":"voip: not available for this call: this call has no waiting room","success":false}},"engine_not_enabled":{"summary":"Calls engine not enabled","value":{"code":409,"error":"calls engine not enabled for this instance (set calls_enabled and reconnect)","success":false}},"tcp_only_route":{"summary":"Mobile TCP-only network route blocks calls","value":{"code":409,"error":"calls_disabled_mobile_tcp_only_route","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/reply":{"post":{"tags":["Chat"],"summary":"Reply to a message with quoted text","description":"Sends a text message that quotes a previous message, built with the library's reply helper so it shows as a reply in the chat.\n\n**Rules:**\n- `to`, `quoted_msg_id` and `content_type` are required. `to` is the chat of both the reply and the quoted message (phone number, user JID or group JID).\n- Only `content_type: \"text\"` is supported, and then `content` is required. `image`, `video`, `document` and `audio` return **400** pointing to the matching `/chat/send/*` endpoint; any other value returns **400** `unsupported content_type`.\n- `quoted_sender` is the author of the quoted message (needed in groups). When omitted or unparsable it defaults to `to`. `quoted_from_me` marks the quoted message as sent by this account.\n- The quote preview carries the placeholder text `(quoted message)`, not the original content.\n- The WhatsApp client must be connected (**500** `client not connected` otherwise); the connection check runs before the body is read.\n- For media replies use `/chat/send/{image,video,document,audio}` with `ContextInfo.stanzaID` and `ContextInfo.participant`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReplyRequest"},"examples":{"reply_text_dm":{"summary":"Reply to a received message in a direct chat","description":"`quoted_sender` is omitted, so the author defaults to `to`.","value":{"to":"5511999999999@s.whatsapp.net","quoted_msg_id":"3EB0F2A1C9D04E8F1234","quoted_from_me":false,"content_type":"text","content":"Perfect, confirmed for tomorrow at 10 AM."}},"reply_in_group":{"summary":"Reply in a group quoting another member","description":"`quoted_sender` identifies the author of the quoted group message.","value":{"to":"120363000000000011@g.us","quoted_msg_id":"3EB0F2A1C9D04E8F5678","quoted_from_me":false,"quoted_sender":"5511888888888@s.whatsapp.net","content_type":"text","content":"I agree with the proposal above."}},"reply_to_own_message":{"summary":"Reply to a message this account sent","description":"`quoted_from_me: true` marks the quoted message as your own.","value":{"to":"5511999999999","quoted_msg_id":"3EB0C767D26A1D6B8A9F","quoted_from_me":true,"content_type":"text","content":"Adding one more detail to my previous message."}}}}}},"responses":{"200":{"description":"The reply was sent and acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatReplyResponse"},"example":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8AA0","timestamp":"2026-09-15T10:30:00-03:00","to":"5511999999999@s.whatsapp.net","quoted_msg_id":"3EB0F2A1C9D04E8F1234","content_type":"text"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, a required field is missing, `to` is invalid, or `content_type`/`content` is not supported.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_request_body":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode request body","success":false}},"missing_fields":{"summary":"to, quoted_msg_id or content_type missing","value":{"code":400,"error":"to, quoted_msg_id and content_type are required","success":false}},"invalid_to":{"summary":"to is not a valid number or JID","value":{"code":400,"error":"invalid to JID","success":false}},"missing_content":{"summary":"Text reply without content","value":{"code":400,"error":"content is required for content_type=text","success":false}},"media_content_type":{"summary":"Media content type","value":{"code":400,"error":"content_type=\"image\" not supported in /chat/reply; use /chat/send/image with quoted_msg_id","success":false}},"unsupported_content_type":{"summary":"Unknown content type","value":{"code":400,"error":"unsupported content_type \"sticker\"","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the client is not connected, or the reply could not be built or sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"send_failed":{"summary":"Reply could not be sent","value":{"code":500,"error":"failed to send reply: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/link":{"post":{"tags":["Community"],"summary":"Link a group to a community","description":"Adds an existing group to a community (parent group) as a sub-group. The session must be an admin of the community\nand of the group being linked.\n\n**Rules:**\n- `parent_group` (community JID) and `child_group` (group JID) are required and must both be non-empty.\n- Both values are parsed as JIDs; an unparsable value returns **400** naming the field.\n- Any WhatsApp refusal (not an admin, group already linked elsewhere, not a community) returns the generic **500** `failed to link group`; the reason is only logged.\n- A refusal can arrive **inside a successful IQ**, as `<group error=\"409\">` (already linked) or `<group error=\"400\">`.\n  Those are detected and reported as **500** too, so a `200` here means the link really happened. Confirm with\n  `GET /group/info` (`LinkedParentJID`) or `POST /community/sub-groups` when the caller needs proof.\n- **Rate limit:** linking and unlinking the same group repeatedly makes WhatsApp answer `429 rate-overlimit`, which also\n  surfaces as the generic **500**. The limit is per group — a different group still links normally. Wait a few minutes\n  before retrying; the previous state is unchanged.\n\n**Use Cases:**\n- Bring department groups under one company community\n- Attach a newly created project group to an existing community\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityLinkRequest"},"examples":{"link":{"summary":"Link a group to a community","description":"The community JID goes in `parent_group`, the group to attach in `child_group`.","value":{"parent_group":"120363000000000033@g.us","child_group":"120363000000000011@g.us"}}}}}},"responses":{"200":{"description":"Group linked; the normalized JIDs are echoed back.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityLinkResponse"},"example":{"code":200,"data":{"success":true,"message":"Group linked to community successfully","parent_group":"120363000000000033@g.us","child_group":"120363000000000011@g.us"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, a missing field, or an unparsable JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"parent_group or child_group missing","value":{"code":400,"error":"missing parent_group or child_group in payload","success":false}},"invalid_parent":{"summary":"parent_group is not a valid JID","value":{"code":400,"error":"invalid parent group JID","success":false}},"invalid_child":{"summary":"child_group is not a valid JID","value":{"code":400,"error":"invalid child group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp refused the link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"link_failed":{"summary":"WhatsApp refused the link","value":{"code":500,"error":"failed to link group","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/unlink":{"post":{"tags":["Community"],"summary":"Unlink a group from its community","description":"Removes a group from the community it is linked to. The gateway first reads the group's info to find the parent\ncommunity, then sends the unlink request; the group itself keeps existing as a standalone group.\n\n**Rules:**\n- `group` is required. The parent community is discovered automatically from `LinkedParentJID`.\n- A group that is not linked to any community returns **400** `group is not linked to any community`.\n- Failures while reading the group (not a member, unknown group) return **500** `failed to get group info`; a refused unlink returns **500** `failed to unlink group`.\n- A refusal can arrive inside a successful IQ as `<group error=\"...\">`; it is detected and reported as **500**, so a\n  `200` means the group really left the community (`LinkedParentJID` becomes empty).\n- **Rate limit:** repeating link/unlink on the same group makes WhatsApp answer `429 rate-overlimit`, which also surfaces\n  as the generic **500**. Wait a few minutes before retrying; the previous state is unchanged.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityUnlinkRequest"},"examples":{"unlink":{"summary":"Unlink a group","description":"Only the sub-group JID is needed; its parent community is looked up first.","value":{"group":"120363000000000011@g.us"}}}}}},"responses":{"200":{"description":"Group unlinked from its community.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityUnlinkResponse"},"example":{"code":200,"data":{"success":true,"message":"Group unlinked from community successfully","group":"120363000000000011@g.us"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, missing or unparsable `group`, or the group has no parent community.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_group":{"summary":"group missing","value":{"code":400,"error":"missing group in payload","success":false}},"invalid_group":{"summary":"group is not a valid JID","value":{"code":400,"error":"invalid group JID","success":false}},"not_linked":{"summary":"Group has no parent community","value":{"code":400,"error":"group is not linked to any community","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, the group info query failed, or WhatsApp refused the unlink.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"group_info_failed":{"summary":"Group info could not be read","value":{"code":500,"error":"failed to get group info","success":false}},"unlink_failed":{"summary":"WhatsApp refused the unlink","value":{"code":500,"error":"failed to unlink group","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/linked":{"get":{"tags":["Community"],"summary":"List the groups linked to a community (legacy GET)","description":"Compatibility alias of `POST /community/linked-groups` kept for existing clients. Returns the sub-groups of a\ncommunity with their names and the announcement-group flag.\n\n**Rules:**\n- Pass the community JID in the `community` query parameter. Old clients that send a JSON body `{\"community\": \"...\"}` with GET are still accepted; the query parameter wins when both are present.\n- `linked_groups` is `null` (and `count` is `0`) when the community has no sub-groups.\n- WhatsApp verdicts are mapped to stable codes: **403** `community_forbidden` (the session cannot inspect this community), **429** `community_rate_limited` with `Retry-After: 5`, **500** `community_linkage_failed` for anything else.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"community","in":"query","required":true,"description":"Community (parent group) JID. Leading and trailing spaces are trimmed.","schema":{"type":"string"},"example":"120363000000000033@g.us"}],"responses":{"200":{"description":"Sub-groups of the community.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedGroupsResponse"},"example":{"code":200,"data":{"success":true,"community":"120363000000000033@g.us","linked_groups":[{"jid":"120363000000000034@g.us","name":"Company Announcements","is_default_sub":true},{"jid":"120363000000000011@g.us","name":"Project Team","is_default_sub":false}],"count":2},"success":true}}}},"400":{"description":"Bad Request: no community given, an invalid JSON body, or an unparsable community JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"missing_community":{"summary":"community missing","value":{"code":400,"error":"missing community in payload","success":false}},"could_not_decode_payload":{"summary":"Legacy JSON body is invalid","value":{"code":400,"error":"could not decode payload","success":false}},"invalid_community":{"summary":"community is not a valid JID","value":{"code":400,"error":"invalid community JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"description":"Forbidden: WhatsApp does not allow this session to inspect the community.\n\n**Pela API pública:** A instância está atribuída a uma conta (ou Revenda) desativada no painel. Desativar ou reativar a conta reflete na API em até 30 s.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":403,"error":"community_forbidden","success":false}},"ACCOUNT_DEACTIVATED":{"summary":"Conta dona desativada","value":{"code":"ACCOUNT_DEACTIVATED","message":"A conta dona desta instância está desativada no painel."}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"description":"Too Many Requests: WhatsApp rate-limited the community query. Retry after the `Retry-After` interval.\n\n**Pela API pública:** Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Always `5`.","schema":{"type":"integer","example":5}}},"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":429,"error":"community_rate_limited","success":false}},"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}}},"500":{"description":"Internal Server Error: no WhatsApp session, or any other failure of the community query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"linkage_failed":{"summary":"Community query failed","value":{"code":500,"error":"community_linkage_failed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/linked-groups":{"post":{"tags":["Community"],"summary":"List the groups linked to a community","description":"Returns the sub-groups of a community (parent group), including its announcement group, with their names.\nThis is the preferred route; `POST /community/sub-groups` and `GET /community/linked` are aliases of the same handler.\n\n**Rules:**\n- Send `community` in the JSON body. A `community` query parameter is also accepted and takes precedence over the body.\n- `is_default_sub: true` marks the community announcement group.\n- `linked_groups` is `null` (and `count` is `0`) when the community has no sub-groups.\n- **403** `community_forbidden` when the session cannot inspect the community; **429** `community_rate_limited` with `Retry-After: 5`; **500** `community_linkage_failed` for other WhatsApp failures.\n\n**Use Cases:**\n- Find the announcement group JID of a community\n- Show the group directory of a community in a dashboard\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"community","in":"query","required":false,"description":"Optional community JID. When present it overrides `community` from the body.","schema":{"type":"string"},"example":"120363000000000033@g.us"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedGroupsRequest"},"examples":{"community":{"summary":"List the sub-groups of a community","description":"Pass the community (parent group) JID.","value":{"community":"120363000000000033@g.us"}}}}}},"responses":{"200":{"description":"Sub-groups of the community.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedGroupsResponse"},"examples":{"with_groups":{"summary":"Community with sub-groups","value":{"code":200,"data":{"success":true,"community":"120363000000000033@g.us","linked_groups":[{"jid":"120363000000000034@g.us","name":"Company Announcements","is_default_sub":true},{"jid":"120363000000000011@g.us","name":"Project Team","is_default_sub":false}],"count":2},"success":true}},"empty":{"summary":"Community without sub-groups","value":{"code":200,"data":{"success":true,"community":"120363000000000033@g.us","linked_groups":null,"count":0},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, missing `community`, or an unparsable community JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_community":{"summary":"community missing","value":{"code":400,"error":"missing community in payload","success":false}},"invalid_community":{"summary":"community is not a valid JID","value":{"code":400,"error":"invalid community JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"description":"Forbidden: WhatsApp does not allow this session to inspect the community.\n\n**Pela API pública:** A instância está atribuída a uma conta (ou Revenda) desativada no painel. Desativar ou reativar a conta reflete na API em até 30 s.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":403,"error":"community_forbidden","success":false}},"ACCOUNT_DEACTIVATED":{"summary":"Conta dona desativada","value":{"code":"ACCOUNT_DEACTIVATED","message":"A conta dona desta instância está desativada no painel."}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"description":"Too Many Requests: WhatsApp rate-limited the community query. Retry after the `Retry-After` interval.\n\n**Pela API pública:** Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Always `5`.","schema":{"type":"integer","example":5}}},"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":429,"error":"community_rate_limited","success":false}},"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}}},"500":{"description":"Internal Server Error: no WhatsApp session, or any other failure of the community query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"linkage_failed":{"summary":"Community query failed","value":{"code":500,"error":"community_linkage_failed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/sub-groups":{"post":{"tags":["Community"],"summary":"List the sub-groups of a community (alias)","description":"Alias of `POST /community/linked-groups`: same handler, same request and same response. Prefer\n`/community/linked-groups` in new integrations.\n\n**Rules:**\n- `community` comes from the JSON body, or from the `community` query parameter, which wins when both are set.\n- The response lists each sub-group with `jid`, `name` and `is_default_sub`; `linked_groups` is `null` when there are none.\n- Rate limiting returns **429** with `Retry-After: 5`; a forbidden community returns **403**.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"community","in":"query","required":false,"description":"Optional community JID. When present it overrides `community` from the body.","schema":{"type":"string"},"example":"120363000000000033@g.us"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedGroupsRequest"},"examples":{"community":{"summary":"List the sub-groups of a community","description":"Pass the community (parent group) JID.","value":{"community":"120363000000000033@g.us"}}}}}},"responses":{"200":{"description":"Sub-groups of the community.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedGroupsResponse"},"example":{"code":200,"data":{"success":true,"community":"120363000000000033@g.us","linked_groups":[{"jid":"120363000000000034@g.us","name":"Company Announcements","is_default_sub":true}],"count":1},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, missing `community`, or an unparsable community JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_community":{"summary":"community missing","value":{"code":400,"error":"missing community in payload","success":false}},"invalid_community":{"summary":"community is not a valid JID","value":{"code":400,"error":"invalid community JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"description":"Forbidden: WhatsApp does not allow this session to inspect the community.\n\n**Pela API pública:** A instância está atribuída a uma conta (ou Revenda) desativada no painel. Desativar ou reativar a conta reflete na API em até 30 s.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":403,"error":"community_forbidden","success":false}},"ACCOUNT_DEACTIVATED":{"summary":"Conta dona desativada","value":{"code":"ACCOUNT_DEACTIVATED","message":"A conta dona desta instância está desativada no painel."}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"description":"Too Many Requests: WhatsApp rate-limited the community query. Retry after the `Retry-After` interval.\n\n**Pela API pública:** Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. Always `5`.","schema":{"type":"integer","example":5}}},"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":429,"error":"community_rate_limited","success":false}},"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}}},"500":{"description":"Internal Server Error: no WhatsApp session, or any other failure of the community query.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"linkage_failed":{"summary":"Community query failed","value":{"code":500,"error":"community_linkage_failed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/requests":{"post":{"tags":["Community"],"summary":"List pending join requests of a group","description":"Returns the people waiting for admin approval to join a group or community (groups with **Approve new members**\nturned on, see `POST /group/joinapproval`). The session must be an admin.\n\n**Rules:**\n- `group` is required and accepts a group or community JID.\n- Only the requester JID is returned; the request time reported by WhatsApp is not included.\n- `pending_requests` is `null` (and `count` is `0`) when nobody is waiting.\n- Any WhatsApp failure returns the generic **500** `failed to get pending requests`.\n\n**Use Cases:**\n- Review join requests before approving them with `POST /community/requests/update`\n- Alert moderators when requests are waiting\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupRequestsRequest"},"examples":{"group":{"summary":"Pending requests of a group","description":"Pass the group (or community) JID.","value":{"group":"120363000000000011@g.us"}}}}}},"responses":{"200":{"description":"Pending join requests.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupRequestsResponse"},"examples":{"pending":{"summary":"Two people waiting","value":{"code":200,"data":{"success":true,"group":"120363000000000011@g.us","pending_requests":[{"jid":"123456789012345@lid"},{"jid":"5511988888888@s.whatsapp.net"}],"count":2},"success":true}},"none":{"summary":"Nobody waiting","value":{"code":200,"data":{"success":true,"group":"120363000000000011@g.us","pending_requests":null,"count":0},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, or `group` missing or unparsable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_group":{"summary":"group missing","value":{"code":400,"error":"missing group in payload","success":false}},"invalid_group":{"summary":"group is not a valid JID","value":{"code":400,"error":"invalid group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the WhatsApp query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"WhatsApp query failed","value":{"code":500,"error":"failed to get pending requests","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/requests/update":{"post":{"tags":["Community"],"summary":"Approve or reject pending join requests","description":"Approves or rejects people waiting to join a group or community. The session must be an admin.\n\n**Rules:**\n- `group`, `action` and a non-empty `requests` array are required.\n- `action` is case-insensitive: `approve` or `accept` approve; `reject` or `deny` reject. Anything else returns **400**.\n- Every entry of `requests` must parse as a JID (phone numbers are accepted); the first invalid one aborts with **400**.\n- `link_code` is accepted but not used.\n- **200 does not confirm each request.** WhatsApp answers per person, but that list is discarded; check again with `POST /community/requests`.\n- `data.message` is built as `Successfully <action>ed <n> request(s)` from the raw `action`, so `approve` reads `approveed`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityRequestsUpdateRequest"},"examples":{"approve":{"summary":"Approve two requests","description":"Requesters can be given as LIDs, phone JIDs or phone numbers.","value":{"group":"120363000000000011@g.us","action":"approve","requests":["123456789012345@lid","5511988888888@s.whatsapp.net"]}},"reject":{"summary":"Reject one request","description":"The requester is not added to the group.","value":{"group":"120363000000000011@g.us","action":"reject","requests":["5511988888888@s.whatsapp.net"]}}}}}},"responses":{"200":{"description":"WhatsApp accepted the update. `action` and `requests` echo the request as sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityRequestsUpdateResponse"},"examples":{"approved":{"summary":"Two requests approved","value":{"code":200,"data":{"success":true,"message":"Successfully approveed 2 request(s)","group":"120363000000000011@g.us","action":"approve","requests":["123456789012345@lid","5511988888888@s.whatsapp.net"]},"success":true}},"rejected":{"summary":"One request rejected","value":{"code":200,"data":{"success":true,"message":"Successfully rejected 1 request(s)","group":"120363000000000011@g.us","action":"reject","requests":["5511988888888@s.whatsapp.net"]},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, missing fields, an unparsable JID, or an unknown `action`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"group, action or requests missing","value":{"code":400,"error":"missing group, action or requests in payload","success":false}},"invalid_group":{"summary":"group is not a valid JID","value":{"code":400,"error":"invalid group JID","success":false}},"invalid_request_jid":{"summary":"A requests entry is not a valid JID","value":{"code":400,"error":"invalid JID: @s.whatsapp.net","success":false}},"invalid_action":{"summary":"action not accepted","value":{"code":400,"error":"invalid action. Use: approve or reject","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp refused the update.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"WhatsApp refused the update","value":{"code":500,"error":"failed to update group requests","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/create":{"post":{"tags":["Community"],"summary":"Create a community","description":"Creates a new community (parent group) with the session as owner, then tries to link the given groups to it.\n\n**Rules:**\n- `name` is required. `description` is **not sent to WhatsApp**; it is only echoed in the response. Set it afterwards with `POST /group/topic` on the community JID.\n- `groups` is optional. Each entry is linked one by one after creation; unparsable or refused groups are skipped silently, so compare `data.community.linked_groups` with the request.\n- `linked_groups` is `null` when no group was linked.\n- A failed creation returns the generic **500** `failed to create community`; link failures never fail the request.\n\n**Use Cases:**\n- Create a company community and attach existing department groups in one call\n- Start an empty community and add groups later with `POST /community/link`\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCommunityRequest"},"examples":{"with_groups":{"summary":"Community with two existing groups","description":"Groups the session is not allowed to link are skipped without an error.","value":{"name":"Acme Company","description":"Official community of Acme employees","groups":["120363000000000011@g.us","120363000000000012@g.us"]}},"name_only":{"summary":"Empty community","description":"Only the name is required.","value":{"name":"Acme Company"}}}}}},"responses":{"200":{"description":"Community created. `linked_groups` lists only the groups that were actually linked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCommunityResponse"},"examples":{"with_groups":{"summary":"One of two groups linked","value":{"code":200,"data":{"success":true,"message":"Community created successfully","community":{"jid":"120363000000000033@g.us","name":"Acme Company","description":"Official community of Acme employees","linked_groups":["120363000000000011@g.us"]}},"success":true}},"name_only":{"summary":"Empty community","value":{"code":200,"data":{"success":true,"message":"Community created successfully","community":{"jid":"120363000000000033@g.us","name":"Acme Company","description":"","linked_groups":null}},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON or missing `name`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_name":{"summary":"name missing","value":{"code":400,"error":"missing name in payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp refused to create the community.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"create_failed":{"summary":"Creation refused","value":{"code":500,"error":"failed to create community","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/community/announcement":{"post":{"tags":["Community"],"summary":"Send a text announcement to a community","description":"Sends a plain text message to the community's announcement group and returns the WhatsApp message ID.\n\n**Rules:**\n- `community` and `message` are required.\n- With the parent community JID, the message goes to its default announcement sub-group (the parent JID itself is not a chat and WhatsApp rejects it with error 420). The resolved JID is returned in `announcement_group`.\n- Any other JID (for example the announcement group itself, the linked group with `is_default_sub: true` from `POST /community/linked-groups`) receives the message as-is; `announcement_group` then equals `community`.\n- If the sub-group lookup fails, the message is sent to the given JID as-is. For a parent community JID WhatsApp then answers 420 and the route returns **500** `failed to send announcement`; retry, or send to the announcement group JID directly.\n- `linked_groups`, `background_color` and `font` are accepted but **ignored**: no per-group fan-out and no styling are applied.\n- A send failure returns the generic **500** `failed to send announcement`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityAnnouncementRequest"},"examples":{"parent_community":{"summary":"Post using the parent community JID","description":"The gateway resolves the community's default announcement sub-group and sends the text there.","value":{"community":"120363000000000034@g.us","message":"Office closed on Friday for maintenance."}},"announcement_group":{"summary":"Post in the announcement group directly","description":"Uses the JID of the default announcement sub-group (`is_default_sub: true` in `POST /community/linked-groups`); it receives the message as-is.","value":{"community":"120363000000000035@g.us","message":"Office closed on Friday for maintenance."}}}}}},"responses":{"200":{"description":"Message accepted by WhatsApp.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommunityAnnouncementResponse"},"examples":{"parent_community":{"summary":"Parent community JID resolved to its announcement sub-group","value":{"code":200,"data":{"success":true,"message":"Announcement sent successfully","community":"120363000000000034@g.us","announcement_group":"120363000000000035@g.us","message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z"},"success":true}},"announcement_group":{"summary":"Announcement group JID sent as-is","value":{"code":200,"data":{"success":true,"message":"Announcement sent successfully","community":"120363000000000035@g.us","announcement_group":"120363000000000035@g.us","message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z"},"success":true}}}}}},"400":{"description":"Bad Request: invalid JSON, missing fields, or an unparsable community JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"community or message missing","value":{"code":400,"error":"missing community or message in payload","success":false}},"invalid_community":{"summary":"community is not a valid JID","value":{"code":400,"error":"invalid community JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the message could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send announcement","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/resolve-link":{"post":{"tags":["Business"],"summary":"Resolve a business message link","description":"Resolves a WhatsApp business message link (`wa.me/message/…`) and returns the business behind it plus the pre-filled message.\n\n**Features:**\n- `business_info.jid`: business JID\n- `business_info.verified_name` and `verified_level`: verified business name and level (`unknown` when not verified)\n- `business_info.message`: text WhatsApp pre-fills in the input box when the link is opened\n\n**Rules:**\n- `link` is required (`400 missing link in payload`); a body that is not JSON returns `400 could not decode payload`\n- Unknown or expired links return `500 failed to resolve link`\n\n**Use Cases:**\n- Validate a business link before showing it to users\n- Discover which account a campaign link opens\n","requestBody":{"required":true,"description":"Link to resolve.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveBusinessLinkRequest"},"examples":{"full_link":{"summary":"Full wa.me link","description":"Resolves a business message link copied from WhatsApp.","value":{"link":"https://wa.me/message/ABCDEFGHIJKLM1"}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Business behind the link","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Resolution result.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"business_info":{"type":"object","description":"Business resolved from the link.","properties":{"jid":{"type":"string","description":"Business JID.","example":"5511988888888@s.whatsapp.net"},"verified_name":{"type":"string","description":"Verified business name (empty when not verified).","example":"Example Store"},"verified_level":{"type":"string","description":"Verification level reported by WhatsApp.","example":"unknown"},"message":{"type":"string","description":"Message pre-filled when the link is opened.","example":"Hello! I would like to see the catalog."}}}}}}}]},"examples":{"resolved":{"summary":"Link resolved","value":{"code":200,"data":{"success":true,"business_info":{"jid":"5511988888888@s.whatsapp.net","verified_name":"Example Store","verified_level":"unknown","message":"Hello! I would like to see the catalog."}},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `missing link in payload`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"link_missing":{"summary":"link missing","value":{"code":400,"error":"missing link in payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, or WhatsApp could not resolve the link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"unknown_or_expired_link":{"summary":"Unknown or expired link","value":{"code":500,"error":"failed to resolve link","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/contact-qr":{"post":{"tags":["Business"],"summary":"Get or rotate the own contact QR link","description":"Returns the contact QR link (`wa.me/qr/…`) of the connected account, optionally revoking the current one first.\n\n**Features:**\n- `revoked: false` (default) returns the current link\n- `revoked: true` revokes the current link (IQ action `revoke`) and returns the new one; old printed QR codes stop working\n\n**Rules:**\n- The body must be a JSON object; an empty body returns `400 could not decode payload` (send `{}`)\n- `phone` is ignored: the link always belongs to the connected account (`jid` in the response)\n","requestBody":{"required":true,"description":"Whether to rotate the link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactQRRequest"},"examples":{"current":{"summary":"Get current link","description":"Returns the existing contact QR link.","value":{"revoked":false}},"rotate":{"summary":"Revoke and create a new link","description":"Invalidates the previous QR code and returns a new link.","value":{"revoked":true}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Contact QR link","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"QR link of the connected account.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"jid":{"type":"string","description":"JID of the connected account that owns the link.","example":"5511999999999:12@s.whatsapp.net"},"link":{"type":"string","description":"Contact QR link.","example":"https://wa.me/qr/ABCDEFGHIJKLM1"},"revoked":{"type":"boolean","description":"Echo of the `revoked` flag sent in the request.","example":false}}}}}]},"examples":{"current":{"summary":"Current link","value":{"code":200,"data":{"success":true,"jid":"5511999999999:12@s.whatsapp.net","link":"https://wa.me/qr/ABCDEFGHIJKLM1","revoked":false},"success":true}},"rotated":{"summary":"Link rotated","value":{"code":200,"data":{"success":true,"jid":"5511999999999:12@s.whatsapp.net","link":"https://wa.me/qr/NOPQRSTUVWXYZ2","revoked":true},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_invalid_body":{"summary":"Empty or invalid body","value":{"code":400,"error":"could not decode payload","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, or the QR IQ failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"iq_failed":{"summary":"IQ failed","value":{"code":500,"error":"failed to get QR link","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/bots":{"get":{"tags":["Business"],"summary":"List available WhatsApp bots","description":"Lists the AI bots (Meta AI personas) that WhatsApp makes available to the connected account.\n\n**Features:**\n- `bots[]` with `bot_jid` and `persona_id`\n- `count` with the number of bots\n\n**Rules:**\n- No body or query parameters\n- `bots` is `null` when WhatsApp returns no bots\n- Use the `bot_jid` values with `POST /business/bot-profiles`\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Bot list","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Available bots.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"count":{"type":"integer","description":"Number of bots.","example":1},"bots":{"type":"array","nullable":true,"description":"Bots, or null when none.","items":{"type":"object","properties":{"bot_jid":{"type":"string","description":"Bot JID (`@bot`).","example":"867051314767696@bot"},"persona_id":{"type":"string","description":"Persona ID of the bot.","example":"1234567890123456"}}}}}}}}]},"examples":{"one_bot":{"summary":"One bot available","value":{"code":200,"data":{"bots":[{"bot_jid":"867051314767696@bot","persona_id":"1234567890123456"}],"count":1,"success":true},"success":true}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, or the bot list IQ failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"iq_failed":{"summary":"IQ failed","value":{"code":500,"error":"failed to get bot list","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/bot-profiles":{"post":{"tags":["Business"],"summary":"Get bot profiles","description":"Returns profile details (name, description, category and commands) for bots listed by `GET /business/bots`.\n\n**Rules:**\n- `bot_jids` is required (`400 missing bot_jids in payload`)\n- The gateway first loads the bot list; each JID must parse (`400 invalid JID: <value>`) and only JIDs present in the list are queried\n- When none of the JIDs is in the list the route returns `404 no matching bots found`\n","requestBody":{"required":true,"description":"Bot JIDs to describe.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BotProfilesRequest"},"examples":{"one_bot":{"summary":"One bot","description":"Describes a single bot from the bot list.","value":{"bot_jids":["867051314767696@bot"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Bot profiles","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Profiles of the matching bots.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"count":{"type":"integer","description":"Number of profiles returned.","example":1},"profiles":{"type":"array","description":"Bot profiles.","items":{"type":"object","properties":{"jid":{"type":"string","description":"Bot JID.","example":"867051314767696@bot"},"name":{"type":"string","description":"Bot name.","example":"Meta AI"},"description":{"type":"string","description":"Bot description.","example":"Ask me anything."},"category":{"type":"string","description":"Bot category.","example":"Assistant"},"commands":{"type":"array","description":"Slash commands (keys are capitalized).","items":{"type":"object","properties":{"Name":{"type":"string","description":"Command.","example":"/imagine"},"Description":{"type":"string","description":"What the command does.","example":"Create an image from a prompt"}}}}}}}}}}}]},"examples":{"one_profile":{"summary":"One bot profile","value":{"code":200,"data":{"count":1,"success":true,"profiles":[{"jid":"867051314767696@bot","name":"Meta AI","description":"Ask me anything.","category":"Assistant","commands":[{"Name":"/imagine","Description":"Create an image from a prompt"}]}]},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `missing bot_jids in payload`; `invalid JID: bot@@invalid`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"bot_jids_missing":{"summary":"bot_jids missing","value":{"code":400,"error":"missing bot_jids in payload","success":false}},"unparseable_jid":{"summary":"Unparseable JID","value":{"code":400,"error":"invalid JID: bot@@invalid","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"None of the requested JIDs is in the bot list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_matching_bots":{"summary":"No matching bots","value":{"code":404,"error":"no matching bots found","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, or a bot IQ failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"bot_list_failed":{"summary":"Bot list failed","value":{"code":500,"error":"failed to get bot list","success":false}},"profiles_failed":{"summary":"Profiles failed","value":{"code":500,"error":"failed to get bot profiles","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/send":{"post":{"tags":["Business"],"summary":"Send an order message to a seller","description":"Sends an order message (`OrderMessage`) to a seller's chat, either as a legacy summary or as a real order registered in the seller's catalog.\n\n**Modes:**\n- **Legacy summary** (default): sends `order_items`, `order_message` and optional free-form `order_id` without registering anything\n- **`create_order: true`**: registers a real catalog order (1-100 unique lines, `price_amount1000`, one uppercase currency) and sends the server-issued order\n- **`resend_registered_order: true`**: queries an existing order by `order_id` + `order_token` and sends it once, without creating another\n\n**Rules:**\n- `business_jid` is required, and `order_items` unless resending (`400 missing business_jid or order_items`)\n- `create_order` and `resend_registered_order` are mutually exclusive; `create_order` must not include `order_id`; resending needs `order_id` and `order_token`\n- Registration failures return `502`; when the order exists but the message failed, the `502` body is the recovery object (no envelope) with `registered_order` — do not retry as a new order\n- Legacy send failures return `500 failed to send order`\n","requestBody":{"required":true,"description":"Seller, order lines and mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessOrderSendRequest"},"examples":{"create_order":{"summary":"Register a real order","description":"Registers one catalog line with explicit thousandths price and sends the server-issued order.","value":{"business_jid":"5511988888888@s.whatsapp.net","create_order":true,"order_message":"Order for one wooden chair","order_items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"currency":"BRL","price_amount1000":3000000}]}},"legacy_summary":{"summary":"Legacy order summary","description":"Sends an order summary without registering it in the catalog.","value":{"business_jid":"5511988888888@s.whatsapp.net","order_message":"Test order without payment","order_items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"price":"3000.00","currency":"BRL"}]}},"resend":{"summary":"Resend a registered order","description":"Sends an existing registered order again using its ID and token.","value":{"business_jid":"5511988888888@s.whatsapp.net","resend_registered_order":true,"order_id":"1976123456789012","order_token":"AR6example0rderT0kenBase64=="}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Order message sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Order send result.","allOf":[{"$ref":"#/components/schemas/BusinessOrderSendResult"}]}}}]},"examples":{"registered":{"summary":"Registered order sent","value":{"code":200,"data":{"success":true,"order_created":true,"order_reused":false,"order_kind":"registered_order","message":"Order sent successfully","business_jid":"5511988888888@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","order_details":{"item_count":1,"order_id":"1976123456789012"},"registered_order":{"order_id":"1976123456789012","token":"AR6example0rderT0kenBase64==","price":{"subtotal_amount":"3000000","total_amount":"3000000","currency":"BRL","price_status":"PROVIDED"}}},"success":true}},"legacy":{"summary":"Legacy summary sent","value":{"code":200,"data":{"success":true,"order_created":false,"order_reused":false,"order_kind":"legacy_summary","message":"Order sent successfully","business_jid":"5511988888888@s.whatsapp.net","message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","order_details":{"item_count":1,"order_id":""}},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `create_order and resend_registered_order are mutually exclusive`; `registered order ID and token required`; `missing business_jid or order_items`; `invalid business JID`; `real order requires non-negative price_amount1000`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"both_modes":{"summary":"Both modes","value":{"code":400,"error":"create_order and resend_registered_order are mutually exclusive","success":false}},"resend_without_id_or_token":{"summary":"Resend without ID or token","value":{"code":400,"error":"registered order ID and token required","success":false}},"missing_fields":{"summary":"Missing fields","value":{"code":400,"error":"missing business_jid or order_items","success":false}},"invalid_jid":{"summary":"Invalid JID","value":{"code":400,"error":"invalid business JID","success":false}},"line_without_price":{"summary":"Line without price","value":{"code":400,"error":"real order requires non-negative price_amount1000","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, or the legacy order message failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send order","success":false}}}}}},"502":{"description":"Order registration or lookup failed (gateway envelope), or the order exists but its message failed (recovery body without envelope).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/BusinessOrderRecoveryBody"}]},"examples":{"profile_unavailable":{"summary":"Seller catalog profile unavailable","value":{"code":502,"error":"business catalog profile unavailable; order not created","success":false}},"creation_uncertain":{"summary":"Registration outcome uncertain","value":{"code":502,"error":"order creation failed; outcome may require verification before retry","success":false}},"message_send_failed":{"summary":"Order registered, delivery unknown (recovery body)","value":{"success":false,"order_created":true,"order_reused":false,"order_exists":true,"message_sent":null,"message_delivery":"unknown","error":"order_created_message_send_failed","registered_order":{"order_id":"1976123456789012","token":"AR6example0rderT0kenBase64==","price":{"subtotal_amount":"3000000","total_amount":"3000000","currency":"BRL","price_status":"PROVIDED"}}}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/sticker-pack/{packId}":{"get":{"tags":["Business"],"summary":"Fetch sticker pack metadata","description":"Returns the metadata of a public WhatsApp sticker pack plus every sticker with the fields needed to download it through `/chat/downloadsticker`.\n\n**Features:**\n- Pack header: `id`, `name`, `publisher`, `description`, `file_size`, `image_data_hash`, `animated`, `lottie`, tray image and preview image IDs\n- `stickers[]`: `url`, `direct_path`, `media_key` / `file_hash` / `file_enc_hash` (hex), `file_size`, `mimetype`, dimensions, `emojis`, `accessibility_text`, `handle`\n- `sticker_count` with the number of stickers returned\n\n**Rules:**\n- `packId` is required (`400 missing packId in path` when blank)\n- Pack IDs come from a received sticker pack message (`stickerPackMessage.stickerPackID`) or from `https://getstickerpack.whatsapp.com/?p=<packId>`\n- **Public packs only.** A pack built in the app (\"sticker maker\") is not in WhatsApp's public catalog: its\n  `stickerPackID` is a local UUID and this route answers **500** `failed to fetch sticker pack: download failed with\n  status code 404` (measured live on 2026-09-16). Tell the two apart by the ID shape — public packs use an opaque\n  catalog ID, app-made packs a UUID like `73b1c4a8-a09c-4437-930c-4690b2209615`.\n- An app-made pack still arrives complete in the webhook event (`stickerPackMessage` with `directPath`, `mediaKey`,\n  `fileSHA256`, `fileEncSHA256` and the sticker list), but its media uses the sticker-pack media key, not the sticker\n  one, so posting those fields to `/chat/downloadsticker` fails with `invalid media hmac`. Downloading an app-made pack\n  is not exposed by the API today.\n","parameters":[{"name":"packId","in":"path","required":true,"description":"Public sticker pack ID (usually a 32-character hex string from the share link).","schema":{"type":"string"},"example":"8e2a3c1f4b5d6e7f8a9b0c1d2e3f4a5b"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Sticker pack","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Pack metadata and stickers.","allOf":[{"$ref":"#/components/schemas/StickerPack"}]}}}]},"examples":{"pack":{"summary":"Pack with one sticker","value":{"code":200,"data":{"success":true,"id":"8e2a3c1f4b5d6e7f8a9b0c1d2e3f4a5b","name":"Cute Cats","publisher":"Acme Stickers","description":"A pack of expressive cat stickers.","file_size":"1238423","image_data_hash":"f31a4c9e8d7b6a5f4e3d2c1b0a9f8e7d","animated":0,"lottie":0,"preview_image_ids":["1.webp","2.webp"],"tray_image_id":"tray.png","tray_image_preview":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII=","stickers":[{"url":"https://mmg.whatsapp.net/v/t62.15575-24/example-sticker.webp","direct_path":"/v/t62.15575-24/example-sticker.webp","media_key":"5f1d0c2b9a8e7f6d5c4b3a2918070605f4e3d2c1b0a998877665544332211000","file_hash":"a3f1c2d4e5b60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90","file_enc_hash":"b4e2d3c5f6a70819203b4c5d6e7f8091b2c3d4e5f6a70819203b4c5d6e7f8091","file_size":24576,"mimetype":"image/webp","width":512,"height":512,"emojis":["😺"],"accessibility_text":"Smiling orange cat","handle":"01","sticker_hash_without_meta":"c5f3e4d6a7b8091a2b3c4d5e6f708192c3d4e5f6a7b8091a2b3c4d5e6f708192","preview_webp_id":"1_preview.webp"}],"sticker_count":1},"success":true}}}}}},"400":{"description":"Invalid request: `missing packId in path`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_pack_id":{"summary":"Blank pack ID","value":{"code":400,"error":"missing packId in path","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"WhatsApp returned no pack for this ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unknown_pack":{"summary":"Unknown pack","value":{"code":404,"error":"sticker pack not found","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, or the sticker pack request failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"request_failed":{"summary":"Request failed","value":{"code":500,"error":"failed to fetch sticker pack: info query returned status 404: item-not-found","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/{orderID}":{"get":{"tags":["Business"],"summary":"Fetch order details","description":"Resolves an order by its ID and token (both present in the received `OrderMessage`) and returns totals and products.\n\n**Features:**\n- `transport=iq` (default): legacy order lookup over IQ\n- `transport=graphql`: registered buyer order lookup (orders created with `create_order`)\n- Prices are integers in thousandths of the currency\n\n**Rules:**\n- The session is checked first (`500 no session` / `client not connected`)\n- The token is read from the `X-Order-Token` header, falling back to the legacy `token` query parameter (`400 missing X-Order-Token header or legacy token query parameter`)\n- `transport` other than `iq`/`graphql` returns `400 transport must be iq or graphql`\n- Lookup failures return `500 failed to fetch order: <reason>`; an empty result returns `404 order not found`\n","parameters":[{"name":"orderID","in":"path","required":true,"description":"Order ID from the received `OrderMessage`.","schema":{"type":"string"},"example":"1976123456789012"},{"name":"X-Order-Token","in":"header","required":false,"description":"Order token from the `OrderMessage` (preferred; takes precedence over the `token` query parameter).","schema":{"type":"string"},"example":"AR6example0rderT0kenBase64=="},{"name":"token","in":"query","required":false,"description":"Legacy order token. Used only when `X-Order-Token` is absent. Note: the user API token must be sent in the `token` header.","schema":{"type":"string"},"example":"AR6example0rderT0kenBase64=="},{"name":"transport","in":"query","required":false,"description":"`iq` (default, legacy lookup) or `graphql` (registered buyer order).","schema":{"type":"string","enum":["iq","graphql"],"default":"iq"},"example":"iq"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Order details","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Order lookup result.","allOf":[{"$ref":"#/components/schemas/OrderDetailsResponse"}]}}}]},"examples":{"order":{"summary":"Order with one product line","value":{"code":200,"data":{"success":true,"order":{"id":"1976123456789012","created_at":"2026-09-15T11:30:00Z","catalog_id":"7123456789012300","price":{"subtotal":6000000,"total":6000000,"currency":"BRL","price_status":"PROVIDED"},"products":[{"id":"7123456789012345","name":"Wooden chair","quantity":2,"price":3000000,"currency":"BRL","image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg"}]}},"success":true}}}}}},"400":{"description":"Invalid request: `missing X-Order-Token header or legacy token query parameter`; `transport must be iq or graphql`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"token_missing":{"summary":"Token missing","value":{"code":400,"error":"missing X-Order-Token header or legacy token query parameter","success":false}},"unknown_transport":{"summary":"Unknown transport","value":{"code":400,"error":"transport must be iq or graphql","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"WhatsApp returned no order.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"order_not_found":{"summary":"Order not found","value":{"code":404,"error":"order not found","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the WhatsApp request failed: `no session`; `client not connected`; `failed to fetch order: info query returned status 404: item-not-found`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"lookup_failed":{"summary":"Lookup failed","value":{"code":500,"error":"failed to fetch order: info query returned status 404: item-not-found","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/catalog/{businessJID}":{"get":{"tags":["Business"],"summary":"Get a business product catalog","description":"Reads one page of the public catalog of a business (GraphQL `QueryCatalog`) and returns products in a compact shape.\n\n**Features:**\n- `catalog.products[]` with ID, retailer ID, name, description, numeric `price` (thousandths, `null` when the product has no usable price), currency, image URLs and availability\n- `catalog.next_cursor` for the next page (omitted on the last page)\n- In-memory cache for 300 s per user, JID, limit and cursor; `cached: true` marks a cache hit\n\n**Rules:**\n- The session is checked first (`500 no session` / `client not connected`), then the path JID and pagination (`400`)\n- Hidden products and products under Meta review are not returned by this public read; use `GET /business/catalog/own` for the own catalog\n- GraphQL rejections return `500 failed to fetch catalog: upstream query rejected`; other failures return `500 failed to fetch catalog: <reason>`\n- A product without price (or with a non-numeric price) is returned with `price: null`; only a missing upstream page returns `502`\n- `catalog.id` is always empty: WhatsApp does not return a catalog ID on this read\n","parameters":[{"name":"businessJID","in":"path","required":true,"description":"Business phone number or JID (`5511988888888`, `@s.whatsapp.net` or `@lid`).","schema":{"type":"string"},"example":"5511988888888@s.whatsapp.net"},{"name":"limit","in":"query","required":false,"description":"Page size, 1-100 (default 20). Must appear at most once.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"example":20},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from `next_cursor` of the previous page. At most once and 2048 bytes.","schema":{"type":"string","maxLength":2048},"example":"AQHRcursorEXAMPLE"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Catalog page","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Catalog read result.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"cached":{"type":"boolean","description":"True when the page came from the 300 s cache.","example":false},"catalog":{"type":"object","description":"Catalog page.","properties":{"id":{"type":"string","description":"Always empty (not returned by WhatsApp).","example":""},"business_jid":{"type":"string","description":"Business JID without device.","example":"5511988888888@s.whatsapp.net"},"products":{"type":"array","description":"Products on this page.","items":{"$ref":"#/components/schemas/BusinessLegacyProduct"}},"next_cursor":{"type":"string","description":"Cursor for the next page; omitted on the last page.","example":"AQHRcursorEXAMPLE"}}}}}}}]},"examples":{"fresh":{"summary":"First page from WhatsApp","value":{"code":200,"data":{"success":true,"cached":false,"catalog":{"id":"","business_jid":"5511988888888@s.whatsapp.net","products":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":3000000,"currency":"BRL","image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"availability":"in stock"}],"next_cursor":"AQHRcursorEXAMPLE"}},"success":true}},"cached":{"summary":"Same page from the cache","value":{"code":200,"data":{"success":true,"cached":true,"catalog":{"id":"","business_jid":"5511988888888@s.whatsapp.net","products":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":3000000,"currency":"BRL","image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"availability":"in stock"}]}},"success":true}}}}}},"400":{"description":"Invalid request: `invalid JID \"5511@@example\"`; `limit must be between 1 and 100`; `limit must be provided once`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"Invalid JID","value":{"code":400,"error":"invalid JID \"5511@@example\"","success":false}},"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 100","success":false}},"repeated_limit":{"summary":"Repeated limit","value":{"code":400,"error":"limit must be provided once","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the WhatsApp request failed: `no session`; `client not connected`; `failed to fetch catalog: upstream query rejected`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"graphql_rejected":{"summary":"GraphQL rejected","value":{"code":500,"error":"failed to fetch catalog: upstream query rejected","success":false}}}}}},"502":{"description":"WhatsApp returned no catalog page at all. A product without a usable price never fails the page; it is returned with `price` null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_page":{"summary":"Upstream returned no page","value":{"code":502,"error":"catalog upstream returned no page","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products/{businessJID}":{"get":{"tags":["Business"],"summary":"List business products","description":"Lists one page of products from the public catalog of a business (same GraphQL `QueryCatalog` read as the catalog route, without the cache).\n\n**Features:**\n- `products[]` in the compact shape (numeric `price` in thousandths, `null` when the product has no usable price)\n- `next_cursor` for the next page (`null` on the last page)\n\n**Rules:**\n- The session is checked first (`500 no session` / `client not connected`), then the path JID and pagination (`400`)\n- Hidden products and products under Meta review are not returned by this public read; use `GET /business/catalog/own` for the own catalog\n- GraphQL rejections return `500 failed to list products: upstream query rejected`; other failures return `500 failed to list products: <reason>`\n- A product without price (or with a non-numeric price) is returned with `price: null`; only a missing upstream page returns `502`\n","parameters":[{"name":"businessJID","in":"path","required":true,"description":"Business phone number or JID (`5511988888888`, `@s.whatsapp.net` or `@lid`).","schema":{"type":"string"},"example":"5511988888888@s.whatsapp.net"},{"name":"limit","in":"query","required":false,"description":"Page size, 1-100 (default 20). Must appear at most once.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"example":20},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from `next_cursor` of the previous page. At most once and 2048 bytes.","schema":{"type":"string","maxLength":2048},"example":"AQHRcursorEXAMPLE"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Products page","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Product list result.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"products":{"type":"array","description":"Products on this page.","items":{"$ref":"#/components/schemas/BusinessLegacyProduct"}},"next_cursor":{"type":"string","description":"Cursor for the next page; null on the last page.","nullable":true,"example":"AQHRcursorEXAMPLE"}}}}}]},"examples":{"page":{"summary":"Page with one product","value":{"code":200,"data":{"success":true,"products":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":3000000,"currency":"BRL","image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"availability":"in stock"}],"next_cursor":"AQHRcursorEXAMPLE"},"success":true}},"last_page":{"summary":"Last page","value":{"code":200,"data":{"success":true,"products":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":3000000,"currency":"BRL","image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"availability":"in stock"}],"next_cursor":null},"success":true}}}}}},"400":{"description":"Invalid request: `invalid JID \"5511@@example\"`; `limit must be between 1 and 100`; `limit must be provided once`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"Invalid JID","value":{"code":400,"error":"invalid JID \"5511@@example\"","success":false}},"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 100","success":false}},"repeated_limit":{"summary":"Repeated limit","value":{"code":400,"error":"limit must be provided once","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the WhatsApp request failed: `no session`; `client not connected`; `failed to list products: upstream query rejected`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"graphql_rejected":{"summary":"GraphQL rejected","value":{"code":500,"error":"failed to list products: upstream query rejected","success":false}}}}}},"502":{"description":"WhatsApp returned no catalog page at all. A product without a usable price never fails the page; it is returned with `price` null.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_page":{"summary":"Upstream returned no page","value":{"code":502,"error":"catalog upstream returned no page","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections/{businessJID}":{"get":{"tags":["Business"],"summary":"List business product collections","description":"Lists the public collections of a business (GraphQL `QueryProductCollections`) with the product IDs of each one.\n\n**Features:**\n- `collections[]` with `id`, `name`, `product_ids` (up to 100 per collection) and a per-collection `next_cursor`\n- Top-level `next_cursor` for the next page of collections\n\n**Rules:**\n- `limit` is the number of collections per page: 1-**20** (default 20)\n- The session is checked first (`500`), then the path JID and pagination (`400`)\n- Collections or products hidden or under review are not listed\n- GraphQL rejections return `500 failed to list collections: upstream query rejected`\n","parameters":[{"name":"businessJID","in":"path","required":true,"description":"Business phone number or JID (`5511988888888`, `@s.whatsapp.net` or `@lid`).","schema":{"type":"string"},"example":"5511988888888@s.whatsapp.net"},{"name":"limit","in":"query","required":false,"description":"Page size, 1-20 (default 20). Must appear at most once.","schema":{"type":"integer","minimum":1,"maximum":20,"default":20},"example":20},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor from `next_cursor` of the previous page. At most once and 2048 bytes.","schema":{"type":"string","maxLength":2048},"example":"AQHRcursorEXAMPLE"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Collections page","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Collections read result.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"collections":{"type":"array","description":"Collections on this page.","items":{"type":"object","properties":{"id":{"type":"string","description":"Collection ID.","example":"7123456789012350"},"name":{"type":"string","description":"Collection name.","example":"Chairs"},"product_ids":{"type":"array","description":"Product IDs in the collection (first page).","items":{"type":"string"},"example":["7123456789012345","7123456789012346"]},"next_cursor":{"type":"string","description":"Cursor for more products of this collection, when present.","example":"AQHRcursorPRODUCTS"}}}},"next_cursor":{"type":"string","description":"Cursor for the next page of collections; null on the last page.","nullable":true}}}}}]},"examples":{"one_collection":{"summary":"One collection","value":{"code":200,"data":{"success":true,"collections":[{"id":"7123456789012350","name":"Chairs","product_ids":["7123456789012345","7123456789012346"]}],"next_cursor":null},"success":true}}}}}},"400":{"description":"Invalid request: `invalid JID \"5511@@example\"`; `limit must be between 1 and 20`; `limit must be provided once`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_jid":{"summary":"Invalid JID","value":{"code":400,"error":"invalid JID \"5511@@example\"","success":false}},"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 20","success":false}},"repeated_limit":{"summary":"Repeated limit","value":{"code":400,"error":"limit must be provided once","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the WhatsApp request failed: `no session`; `client not connected`; `failed to list collections: upstream query rejected`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"graphql_rejected":{"summary":"GraphQL rejected","value":{"code":500,"error":"failed to list collections: upstream query rejected","success":false}}}}}},"502":{"description":"WhatsApp returned no page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_upstream_page":{"summary":"Empty upstream page","value":{"code":502,"error":"collections upstream returned no page","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/catalog/send":{"post":{"tags":["Business"],"summary":"Send a catalog link message","description":"Sends a plain text message with the catalog link (`https://wa.me/c/<phone>`) of a business.\n\n**Features:**\n- Works for any recipient chat (user, LID or group)\n- Optional `caption` placed before the link\n\n**Rules:**\n- `to` and `business_jid` are required (`400 to and business_jid are required`)\n- `business_jid` may be a phone number, a non-device `@s.whatsapp.net` JID or a `@lid` with a stored phone mapping; it becomes `https://wa.me/c/<phone>`\n- When no phone link can be derived (a `@lid` without a known phone mapping, group or device JIDs, or any other value) the original text is kept: `Catálogo: <business_jid as sent>`, never a `400`\n- The sent text is `<caption>` + blank line + `Catálogo: <link>`; the `Catálogo:` prefix is a fixed Portuguese label written by the gateway\n- Send failures return `500 failed to send catalog: <reason>`\n","requestBody":{"required":true,"description":"Recipient, catalog owner and optional caption.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCatalogSendRequest"},"examples":{"with_caption":{"summary":"Catalog link with caption","description":"Sends the caption, a blank line and the catalog link.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","caption":"Check out our full catalog"}},"link_only":{"summary":"Catalog link only","description":"Sends only the labeled catalog link.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888"}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Catalog link sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Send acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"}}}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net"},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `to and business_jid are required`; `invalid to JID`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"required_fields_missing":{"summary":"Required fields missing","value":{"code":400,"error":"to and business_jid are required","success":false}},"invalid_recipient":{"summary":"Invalid recipient","value":{"code":400,"error":"invalid to JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the send failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send catalog: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/product/send":{"post":{"tags":["Business"],"summary":"Send a product card","description":"Sends a single product card (`ProductMessage`) that opens a catalog product.\n\n**Modes:**\n- **ID only** (no `snapshot`, no `use_catalog`): card with the product ID and `caption` as description; `snapshot_complete: false`\n- **`snapshot`**: explicit card fields (title, description, currency, `price_amount1000`, retailer ID, URL and optional image)\n- **`use_catalog: true`**: loads the real product from the owner's catalog (image downloaded only from `*.whatsapp.net` / `*.fbcdn.net`); `snapshot` fields override single values\n\n**Rules:**\n- `to`, `business_jid` and `product_id` are required (`400 to, business_jid and product_id are required`; `invalid to JID`; `invalid business_jid`)\n- When a phone/LID mapping is known the owner's LID is used; the given owner is never replaced by the session owner\n- Invalid snapshots return `400 invalid snapshot` or the product builder error; invalid images return `400` (base64, size, JPEG/PNG, 40 megapixels)\n- Catalog failures return `502` (hidden or under-review products are not readable publicly); image uploads failing return `500 failed to upload product image`\n- `quoted_msg_id` applies only to a real outgoing message stored for this chat; otherwise the card is sent unquoted (`quoted_message_reason`: `not_requested`, `applied`, `not_available_in_session_chat`, or `lookup_failed` when the stored history could not be read)\n- With `use_catalog`, a product without a usable integer price is sent without price instead of failing\n- The body is limited to 24 MiB\n\n**Response:**\n- `product_image_applied` reports protocol inclusion, not confirmation that the recipient rendered the image\n","requestBody":{"required":true,"description":"Recipient, catalog owner, product and card mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessProductSendRequest"},"examples":{"id_only":{"summary":"ID-only product card","description":"Minimal card that references the product ID.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","product_id":"7123456789012345","caption":"Our best seller"}},"snapshot":{"summary":"Explicit snapshot","description":"Card with explicit title, price, retailer ID and URL.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","product_id":"7123456789012345","caption":"Our best seller","snapshot":{"title":"Wooden chair","description":"Solid wood chair with natural finish.","currency":"BRL","price_amount1000":3000000,"retailer_id":"CHAIR-001","url":"https://example.com/products/chair"}}},"use_catalog":{"summary":"Catalog data with a title override and quote","description":"Loads the product from the catalog, overrides only the title and quotes an earlier outgoing message.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","product_id":"7123456789012345","use_catalog":true,"snapshot":{"title":"Wooden chair - 20% off"},"quoted_msg_id":"3EB0C767D26A1D6B8A9F"}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Product card sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Send acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"snapshot_complete":{"type":"boolean","description":"True when the card was built from `snapshot` or the catalog.","example":true},"product_image_applied":{"type":"boolean","description":"True when a product image was included in the message.","example":true},"quoted_message_applied":{"type":"boolean","description":"True when the message quotes `quoted_msg_id`.","example":false},"quoted_message_reason":{"type":"string","description":"Quote outcome.","enum":["not_requested","applied","not_available_in_session_chat"],"example":"not_requested"}}}}}]},"examples":{"id_only":{"summary":"ID-only card","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","snapshot_complete":false,"product_image_applied":false,"quoted_message_applied":false,"quoted_message_reason":"not_requested"},"success":true}},"catalog_card":{"summary":"Catalog card with image and quote","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","snapshot_complete":true,"product_image_applied":true,"quoted_message_applied":true,"quoted_message_reason":"applied"},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `to, business_jid and product_id are required`; `invalid snapshot`; `invalid product image base64 or size`; `product image must be JPEG or PNG`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"required_fields_missing":{"summary":"Required fields missing","value":{"code":400,"error":"to, business_jid and product_id are required","success":false}},"invalid_snapshot":{"summary":"Invalid snapshot","value":{"code":400,"error":"invalid snapshot","success":false}},"image_too_large":{"summary":"Image too large","value":{"code":400,"error":"invalid product image base64 or size","success":false}},"image_not_jpeg_or_png":{"summary":"Image not JPEG or PNG","value":{"code":400,"error":"product image must be JPEG or PNG","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, media upload, quote lookup or send failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"upload_failed":{"summary":"Upload failed","value":{"code":500,"error":"failed to upload product image","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send product: server returned error 479","success":false}}}}}},"502":{"description":"The catalog product or its image could not be loaded (`use_catalog`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"product_not_readable":{"summary":"Product not readable","value":{"code":502,"error":"catalog product unavailable","success":false}},"image_host_not_allowed":{"summary":"Image host not allowed","value":{"code":502,"error":"catalog image host is not allowed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/product-list/send":{"post":{"tags":["Business"],"summary":"Send a product list message","description":"Sends a product list (`ListMessage` of type product list) with one or more sections of catalog products.\n\n**Features:**\n- 1-10 sections, up to 30 products in total\n- Optional header thumbnail from a catalog product (`use_catalog: true`, `header_product_id`)\n- The list button text is the fixed Portuguese label `Ver produtos`; an empty `header` becomes `Catálogo`\n\n**Rules:**\n- `to`, `business_jid` and `sections` are required (`400 to, business_jid and sections are required`)\n- Lists outside the official builder limits (more than 10 sections or 30 products, duplicate IDs, long texts) are still sent in the original unvalidated format, as before; recipients' apps may not render them\n- With `use_catalog`, `header_product_id` must belong to the sections (`400 header_product_id must belong to sections`); catalog or image failures return `502`\n- Send failures return `500 failed to send product list: <reason>`\n","requestBody":{"required":true,"description":"Recipient, catalog owner, texts and sections.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessProductListSendRequest"},"examples":{"two_sections":{"summary":"Product list with two sections","description":"Header, body, footer and two sections of products.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","header":"Weekly offers","body":"Select the items you want","footer":"Valid until Sunday","sections":[{"title":"Chairs","products":[{"product_id":"7123456789012345"},{"product_id":"7123456789012346"}]},{"title":"Tables","products":[{"product_id":"7123456789012347"}]}]}},"catalog_header":{"summary":"Header thumbnail from the catalog","description":"Uses the image of `header_product_id` as the header thumbnail.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","use_catalog":true,"header_product_id":"7123456789012346","body":"Select the items you want","sections":[{"title":"Chairs","products":[{"product_id":"7123456789012345"},{"product_id":"7123456789012346"}]}]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Product list sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Send acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"product_image_applied":{"type":"boolean","description":"True when a header thumbnail was included.","example":false},"sections":{"type":"integer","description":"Number of sections sent.","example":2}}}}}]},"examples":{"two_sections":{"summary":"Two sections acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","product_image_applied":false,"sections":2},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `to, business_jid and sections are required`; `invalid to JID`; `invalid business_jid`; with `use_catalog`, `header_product_id must belong to sections`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"required_fields_missing":{"summary":"Required fields missing","value":{"code":400,"error":"to, business_jid and sections are required","success":false}},"header_product_outside_sections":{"summary":"Header product outside sections","value":{"code":400,"error":"header_product_id must belong to sections","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the send failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send product list: server returned error 479","success":false}}}}}},"502":{"description":"The header product or its image could not be loaded (`use_catalog`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"header_product_not_readable":{"summary":"Header product not readable","value":{"code":502,"error":"catalog header product unavailable","success":false}},"header_product_without_image":{"summary":"Header product without image","value":{"code":502,"error":"catalog header product image unavailable","success":false}},"invalid_header_image":{"summary":"Invalid header image","value":{"code":502,"error":"invalid catalog header image","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/shop/send":{"post":{"tags":["Business"],"summary":"Send a shop link message","description":"Sends a plain text message with the shop link (`https://wa.me/c/<phone>`) of a business.\n\n**Features:**\n- Text is `<caption> <link>`\n- Without `caption` the gateway writes the fixed Portuguese label `Acesse nossa loja:` before the link\n\n**Rules:**\n- The session is checked first (`500`), then the body (`400`)\n- `to` and `business_jid` are required (`400 to and business_jid are required`)\n- `business_jid` may be a phone number, a non-device `@s.whatsapp.net` JID or a `@lid` with a stored phone mapping; it becomes `https://wa.me/c/<phone>`\n- When no phone link can be derived (a `@lid` without a known phone mapping, group or device JIDs, or any other value) the original text is kept: `<caption> wa.me/<business_jid as sent>`, never a `400`\n- Send failures return `500 failed to send shop: <reason>`\n","requestBody":{"required":true,"description":"Recipient, shop owner and optional caption.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessShopSendRequest"},"examples":{"shop_link":{"summary":"Shop link with caption","description":"Sends `Visit our official shop: https://wa.me/c/5511988888888`.","value":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","caption":"Visit our official shop:"}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Shop link sent","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Send acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"}}}}}]},"examples":{"sent":{"summary":"Message acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net"},"success":true}}}}}},"400":{"description":"Invalid request: `could not decode payload`; `to and business_jid are required`; `invalid to JID`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"body_is_not_json":{"summary":"Body is not JSON","value":{"code":400,"error":"could not decode payload","success":false}},"required_fields_missing":{"summary":"Required fields missing","value":{"code":400,"error":"to and business_jid are required","success":false}},"invalid_recipient":{"summary":"Invalid recipient","value":{"code":400,"error":"invalid to JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the send failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"send_failed":{"summary":"Send failed","value":{"code":500,"error":"failed to send shop: server returned error 479","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/device/users":{"post":{"tags":["Device"],"summary":"List the devices of WhatsApp accounts","description":"Lists the devices (phone and companion devices such as WhatsApp Web or Desktop) registered to one or more WhatsApp accounts, using the library device cache or a WhatsApp usync query.\n\n**Rules:**\n- `user_jids` is required and must be a non-empty array. Each item may be a phone number with country code, a phone JID or a LID; the first invalid item aborts with **400**.\n- The session's own device is never included, even when your own JID is queried.\n- A missing WhatsApp session returns **500** `no session`; a failed query returns **500**.\n\n**Response:**\n- One flat `devices` list for all requested accounts, with `count` items.\n- `platform` is derived from the device slot number (`device_id`) with the same table as `POST /device/platform`; it is not the real client platform. Slot `0` is the primary phone and shows `UNKNOWN`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserDevicesRequest"},"examples":{"two_users":{"summary":"Devices of two accounts","description":"Mixes a phone JID and a bare phone number.","value":{"user_jids":["5511999999999@s.whatsapp.net","5511988888888"]}},"lid_user":{"summary":"Devices of an account addressed by LID","description":"LIDs are accepted; returned device JIDs keep the LID server.","value":{"user_jids":["123456789012345@lid"]}}}}}},"responses":{"200":{"description":"Devices of the requested accounts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceUsersResponse"},"example":{"code":200,"data":{"success":true,"devices":[{"user_jid":"5511999999999@s.whatsapp.net","device_jid":"5511999999999@s.whatsapp.net","device_id":0,"platform":"UNKNOWN"},{"user_jid":"5511999999999@s.whatsapp.net","device_jid":"5511999999999:7@s.whatsapp.net","device_id":7,"platform":"DESKTOP"},{"user_jid":"5511988888888@s.whatsapp.net","device_jid":"5511988888888@s.whatsapp.net","device_id":0,"platform":"UNKNOWN"}],"count":3},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `user_jids` missing or empty, or an item is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_user_jids":{"summary":"user_jids missing or empty","value":{"code":400,"error":"missing user_jids in payload","success":false}},"invalid_jid":{"summary":"An item cannot be parsed","value":{"code":400,"error":"invalid JID: @s.whatsapp.net","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the device query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"Device query failed","value":{"code":500,"error":"failed to get devices","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/device/users/context":{"post":{"tags":["Device"],"summary":"List account devices with a custom timeout","description":"Lists the devices of one or more WhatsApp accounts like `POST /device/users`, but runs the query under a caller-defined timeout and echoes a free-text `context` tag back in the response.\n\n**Rules:**\n- `user_jids` is required and must be a non-empty array of phone numbers, phone JIDs or LIDs.\n- `timeout` is a Go duration in **nanoseconds** (`10000000000` = 10 s). Omitted or `0` means 30 s. Small numbers such as `10` mean 10 ns and make the query fail at once.\n- The timeout context is not tied to the HTTP request; a timeout returns **500** `failed to get devices` (there is no 408).\n- The session's own device is never included.\n\n**Response:**\n- Same `devices` and `count` as `POST /device/users`, plus `context` (empty string when not sent).\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceUsersContextRequest"},"examples":{"with_timeout":{"summary":"10-second timeout with a tag","description":"The tag is echoed in `data.context` and written to the gateway logs.","value":{"user_jids":["5511999999999@s.whatsapp.net","5511977777777"],"context":"crm-sync","timeout":10000000000}},"default_timeout":{"summary":"Default 30-second timeout","description":"Without `timeout` the query may take up to 30 seconds.","value":{"user_jids":["123456789012345@lid"]}}}}}},"responses":{"200":{"description":"Devices of the requested accounts and the echoed tag.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceUsersContextResponse"},"example":{"code":200,"data":{"success":true,"devices":[{"user_jid":"5511999999999@s.whatsapp.net","device_jid":"5511999999999@s.whatsapp.net","device_id":0,"platform":"UNKNOWN"},{"user_jid":"5511999999999@s.whatsapp.net","device_jid":"5511999999999:7@s.whatsapp.net","device_id":7,"platform":"DESKTOP"}],"count":2,"context":"crm-sync"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON (including a non-integer `timeout`), `user_jids` missing or empty, or an item is not a valid number/JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON or timeout is not an integer","value":{"code":400,"error":"could not decode payload","success":false}},"missing_user_jids":{"summary":"user_jids missing or empty","value":{"code":400,"error":"missing user_jids in payload","success":false}},"invalid_jid":{"summary":"An item cannot be parsed","value":{"code":400,"error":"invalid JID: @s.whatsapp.net","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the device query failed or timed out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"Query failed or exceeded the timeout","value":{"code":500,"error":"failed to get devices","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/device/linked":{"get":{"tags":["Device"],"summary":"List devices linked to your account","description":"Lists the devices registered to the connected account: the primary phone and the other companion devices (WhatsApp Web, Desktop, other gateways).\n\n**Rules:**\n- No query parameters or body. The session must be paired; before pairing the call returns **500** `not logged in`.\n- The library never returns the session's own device, so this gateway is not in the list and `is_current` is normally `false` for every entry.\n\n**Response:**\n- `jid` is the account JID; `linked_devices` has `count` items.\n- `platform` is derived from the device slot number with the table of `POST /device/platform`, not detected from the real client.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Devices registered to the account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedDevicesResponse"},"example":{"code":200,"data":{"success":true,"jid":"5511999999999:12@s.whatsapp.net","linked_devices":[{"device_jid":"5511999999999@s.whatsapp.net","device_id":0,"platform":"UNKNOWN","is_current":false},{"device_jid":"5511999999999:7@s.whatsapp.net","device_id":7,"platform":"DESKTOP","is_current":false}],"count":2},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, session not paired, or the device query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_logged_in":{"summary":"Session not paired yet","value":{"code":500,"error":"not logged in","success":false}},"query_failed":{"summary":"Device query failed","value":{"code":500,"error":"failed to get linked devices","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/device/platform":{"post":{"tags":["Device"],"summary":"Translate a device ID to a platform name","description":"Returns the platform label this gateway associates with a numeric device ID. It is a local lookup table: no WhatsApp session or network call is involved.\n\n**Rules:**\n- `device_id` is optional; a missing field is treated as `0`.\n- Known IDs: 0 `UNKNOWN`, 1 `CHROME`, 2 `FIREFOX`, 3 `IE`, 4 `OPERA`, 5 `SAFARI`, 6 `EDGE`, 7 `DESKTOP`, 8 `IPAD`, 9 `ANDROID_TABLET`, 10 `OHANA`, 11 `ALOHA`, 12 `CATALINA`, 13 `TCL_TV`. Any other number returns `UNKNOWN`.\n- A non-integer `device_id` fails to decode and returns **400**.\n\n**Use Cases:**\n- Label the `device_id` values returned by `POST /device/users` and `GET /device/linked`\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevicePlatformRequest"},"examples":{"desktop":{"summary":"Known ID","description":"Device ID 7 maps to `DESKTOP`.","value":{"device_id":7}},"unknown":{"summary":"ID outside the table","description":"Unmapped IDs return `UNKNOWN`.","value":{"device_id":42}}}}}},"responses":{"200":{"description":"Platform label for the device ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DevicePlatformResponse"},"example":{"code":200,"data":{"success":true,"device_id":7,"platform":"DESKTOP"},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON or `device_id` is not an integer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":400,"error":"could not decode payload","success":false}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: the JSON response could not be serialized. Not expected in practice, because the payload only holds an integer and strings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"json: error calling MarshalJSON","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/privacy/settings":{"get":{"tags":["Privacy"],"summary":"Get privacy settings","description":"Returns the privacy settings of the connected account grouped under `privacy_settings`, using the settings cached by the WhatsApp library (fetched from WhatsApp on first use).\n\n**Rules:**\n- No query parameters or body.\n- If WhatsApp cannot be queried, the call still returns **200** with empty strings. Use `GET /user/privacy/settings` when a failed fetch must surface as an error.\n\n**Values:**\n- `group_add`, `last_seen`, `status`, `profile`: `all`, `contacts`, `contact_blacklist` or `none`.\n- `read_receipts`: `all` or `none`. `online`: `all` or `match_last_seen`. `call_add`: `all` or `known`.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Cached privacy settings.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacySettingsResponse"},"examples":{"fetched":{"summary":"Settings available","value":{"code":200,"data":{"success":true,"privacy_settings":{"group_add":"contacts","last_seen":"contacts","status":"contacts","profile":"all","read_receipts":"all","online":"match_last_seen","call_add":"all"}},"success":true}},"fetch_failed":{"summary":"WhatsApp could not be queried","value":{"code":200,"data":{"success":true,"privacy_settings":{"group_add":"","last_seen":"","status":"","profile":"","read_receipts":"","online":"","call_add":""}},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"post":{"tags":["Privacy"],"summary":"Change a privacy setting","description":"Changes one privacy setting of the connected account, such as who can see your last seen or add you to groups.\n\n**Rules:**\n- `setting` and `value` are required; both are case-insensitive.\n- `setting`: `group_add`, `last_seen`, `status`, `profile`, `read_receipts`, `online` or `call_add`.\n- `value`: `all`, `contacts`, `contact_blacklist` or `none`. The gateway does not accept `match_last_seen` or `known`, so `online` and `call_add` can only be set to `all` here.\n- WhatsApp rejects combinations it does not support (for example `read_receipts` with `contacts`) with **500**.\n- `users` is validated (an invalid JID returns **400**) but then ignored: per-contact exception lists are not applied by this endpoint.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPrivacySettingRequest"},"examples":{"last_seen_contacts":{"summary":"Last seen visible to contacts only","description":"Hides the last seen time from people who are not in your contacts.","value":{"setting":"last_seen","value":"contacts"}},"groups_contacts":{"summary":"Only contacts can add you to groups","description":"People outside your contacts must send an invite instead.","value":{"setting":"group_add","value":"contacts"}},"read_receipts_off":{"summary":"Turn off read receipts","description":"Stops sending blue ticks; you also stop seeing them from others.","value":{"setting":"read_receipts","value":"none"}}}}}},"responses":{"200":{"description":"Setting changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacySetSettingResponse"},"example":{"code":200,"data":{"success":true,"message":"Privacy setting last_seen updated to contacts","setting":"last_seen","value":"contacts"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `setting`/`value` missing or not allowed, or an invalid JID in `users`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"setting or value missing","value":{"code":400,"error":"missing setting or value in payload","success":false}},"invalid_setting":{"summary":"setting not in the allowed list","value":{"code":400,"error":"invalid setting type","success":false}},"invalid_value":{"summary":"value not in the allowed list","value":{"code":400,"error":"invalid privacy value","success":false}},"invalid_user":{"summary":"An item of users cannot be parsed","value":{"code":400,"error":"invalid JID: @s.whatsapp.net","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp rejected the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"WhatsApp rejected the change","value":{"code":500,"error":"failed to update privacy setting","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/privacy/disappearing-timer":{"post":{"tags":["Privacy"],"summary":"Set the default disappearing-message timer","description":"Sets the default disappearing-message timer applied to new one-to-one chats of the connected account. Existing chats keep their own timer.\n\n**Rules:**\n- `timer` is required and case-insensitive: `24h`, `7d`, `90d`, or `off` (also `0`) to disable.\n- Any other value returns **400**; custom durations are not supported.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisappearingTimerRequest"},"examples":{"seven_days":{"summary":"Messages disappear after 7 days","description":"New chats start with a 7-day timer.","value":{"timer":"7d"}},"one_day":{"summary":"Messages disappear after 24 hours","description":"The shortest timer offered by WhatsApp.","value":{"timer":"24h"}},"disable":{"summary":"Turn the default timer off","description":"New chats start without disappearing messages.","value":{"timer":"off"}}}}}},"responses":{"200":{"description":"Default timer updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacyDisappearingTimerResponse"},"example":{"code":200,"data":{"success":true,"message":"Default disappearing timer set to 7d","timer":"7d"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `timer` missing, or not one of the allowed values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_timer":{"summary":"timer missing or empty","value":{"code":400,"error":"missing timer in payload","success":false}},"invalid_timer":{"summary":"timer not allowed","value":{"code":400,"error":"invalid timer value. Use: 24h, 7d, 90d, or off","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp rejected the timer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"update_failed":{"summary":"WhatsApp rejected the timer","value":{"code":500,"error":"failed to set disappearing timer","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/privacy/blocklist":{"get":{"tags":["Privacy"],"summary":"List blocked contacts","description":"Returns the JIDs blocked by the connected account, fetched from WhatsApp.\n\n**Rules:**\n- No query parameters or body; the list is always fetched from WhatsApp.\n- A failed WhatsApp query returns **500** `failed to get blocklist`.\n\n**Response:**\n- `blocked_contacts` is `null` (not an empty array) when nobody is blocked; `count` is then `0`.\n- Entries can be phone JIDs or LIDs, as reported by WhatsApp.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Blocked JIDs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BlocklistResponse"},"examples":{"with_blocked":{"summary":"Two blocked contacts","value":{"code":200,"data":{"success":true,"blocked_contacts":["5511977777777@s.whatsapp.net","123456789012347@lid"],"count":2},"success":true}},"empty":{"summary":"Nobody blocked","value":{"code":200,"data":{"success":true,"blocked_contacts":null,"count":0},"success":true}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the blocklist query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"query_failed":{"summary":"Blocklist query failed","value":{"code":500,"error":"failed to get blocklist","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"post":{"tags":["Privacy"],"summary":"Block or unblock contacts","description":"Blocks or unblocks one or more contacts of the connected account. Each contact is sent to WhatsApp as a separate request.\n\n**Rules:**\n- `action` (`block` or `unblock`, case-insensitive) and a non-empty `users` array are required.\n- Each item of `users` may be a phone number with country code or a JID; the first invalid item aborts with **400** before anything is sent.\n- The request fails with **500** only when every contact failed. Partial failures still return **200**, and `message` counts all requested contacts, not only the successful ones.\n\n**Response:**\n- `message` is built from `action` as sent (for example `Successfully blocked 2 contact(s)`); `action` and `users` echo the request.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateBlocklistRequest"},"examples":{"block":{"summary":"Block two contacts","description":"Accepts phone numbers and JIDs in the same list.","value":{"action":"block","users":["5511977777777","5511966666666@s.whatsapp.net"]}},"unblock":{"summary":"Unblock one contact","description":"Removes the contact from the blocklist.","value":{"action":"unblock","users":["5511977777777"]}}}}}},"responses":{"200":{"description":"At least one contact was updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PrivacyBlocklistUpdateResponse"},"example":{"code":200,"data":{"success":true,"message":"Successfully blocked 2 contact(s)","action":"block","users":["5511977777777","5511966666666@s.whatsapp.net"]},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, `action` or `users` missing, unknown action, or an invalid item in `users`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode payload","success":false}},"missing_fields":{"summary":"action or users missing","value":{"code":400,"error":"missing action or users in payload","success":false}},"invalid_action":{"summary":"action is neither block nor unblock","value":{"code":400,"error":"invalid action. Use: block or unblock","success":false}},"invalid_user":{"summary":"An item of users cannot be parsed","value":{"code":400,"error":"invalid JID: @s.whatsapp.net","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or WhatsApp rejected every contact in the list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"all_failed":{"summary":"Every contact failed","value":{"code":500,"error":"failed to update blocklist","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/privacy/status":{"get":{"tags":["Privacy"],"summary":"Get the status-privacy setting","description":"Returns only the \"status\" privacy setting of the connected account: who can see your status updates. Reads the same cached settings as `GET /privacy/settings`.\n\n**Rules:**\n- No query parameters or body.\n- When WhatsApp cannot be queried, `status_privacy` is an empty string and the response is still **200**.\n\n**Response:**\n- `status_privacy`: `all`, `contacts`, `contact_blacklist` or `none`.\n- `description` is a fixed explanatory string.\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Status privacy setting.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusPrivacyResponse"},"example":{"code":200,"data":{"success":true,"status_privacy":"contacts","description":"Status privacy setting (all, contacts, contact_blacklist, or none)"},"success":true}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":500,"error":"no session","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/cart":{"put":{"tags":["Business"],"summary":"Enable or disable the shopping cart","description":"Turns the catalog shopping cart (\"Add to cart\") on or off for the connected business account.\n\n**Rules:**\n- `enabled` is required (`400 enabled is required`)\n- WhatsApp must echo the new `cart_enabled` value; a missing or different value returns `502`\n- On success `data.data` is `null` and this user's catalog cache is cleared\n\n**Use Cases:**\n- Disable the cart for catalogs used only for browsing\n- Re-enable ordering after a stock break\n","requestBody":{"required":true,"description":"Target cart state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementEnabledRequest"},"examples":{"enable":{"summary":"Enable cart","description":"Buyers can add products to a cart and send an order.","value":{"enabled":true}},"disable":{"summary":"Disable cart","description":"The catalog stays visible but the cart is turned off.","value":{"enabled":false}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Cart setting updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"updated":{"summary":"Cart setting applied","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `enabled is required`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"enabled_missing":{"summary":"enabled missing","value":{"code":400,"error":"enabled is required","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"server_did_not_echo_the_value":{"summary":"Server did not echo the value","value":{"code":502,"error":"business operation failed: update business cart setting: business commerce settings response is missing cart_enabled","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/catalog":{"post":{"tags":["Business"],"summary":"Create the business catalog","description":"Creates the product catalog of the connected business account (Meta mutation `xfb_whatsapp_catalog_create`).\n\n**Use Cases:**\n- Run once on accounts that have no catalog yet, before `POST /business/products`\n\n**Rules:**\n- The body may be omitted or be an empty object `{}`; any property returns `400 invalid JSON body (maximum 24 MiB)`\n- If the server response has no `product_catalog` the call fails with `502`\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","requestBody":{"required":false,"description":"Empty object `{}`; the body may also be omitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessEmptyRequest"},"examples":{"empty":{"summary":"Empty object","description":"No properties are accepted; sending `{}` is equivalent to omitting the body.","value":{}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Catalog created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"created":{"summary":"Catalog created","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"response_without_catalog":{"summary":"Response without catalog","value":{"code":502,"error":"business operation failed: business catalog response is missing product_catalog","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/catalog/{businessJID}/products/query":{"post":{"tags":["Business"],"summary":"Get several catalog products by ID","description":"Fetches up to 100 products from the public catalog of `businessJID` in one call (GraphQL `QueryProductListCatalog`).\n\n**Features:**\n- `data.data` is an array in the same order as `product_ids`\n- Each item has the full product shape (prices, media, sale price, review status)\n\n**Rules:**\n- `product_ids` is required: 1-100 unique IDs of 1-256 bytes (`400 provide 1-100 IDs`, `duplicate ID`, `ID must contain 1-256 bytes`)\n- `businessJID` must be `@s.whatsapp.net` or `@lid`\n- If any requested product is missing (hidden, under review or deleted) the whole call fails with `502`\n- Read-only: the catalog cache is not touched\n","parameters":[{"name":"businessJID","in":"path","required":true,"description":"Business owner JID: a phone JID (`@s.whatsapp.net`) or LID (`@lid`). Other servers return `400 businessJID must be a user JID`.","schema":{"type":"string"},"example":"5511988888888@s.whatsapp.net"}],"requestBody":{"required":true,"description":"Product IDs to fetch (1-100 unique).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementIDsRequest"},"examples":{"single":{"summary":"One product","description":"Fetch a single product by ID.","value":{"product_ids":["7123456789012345"]}},"several":{"summary":"Several products","description":"Fetch two products; the response keeps this order.","value":{"product_ids":["7123456789012345","7123456789012346"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Products in request order","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"array","description":"Products in the order of `product_ids`.","items":{"$ref":"#/components/schemas/BusinessCatalogProduct"}}}}}}]},"examples":{"one_product":{"summary":"One product","value":{"code":200,"data":{"data":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"APPROVED"}}],"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `provide 1-100 IDs`; `duplicate ID`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`; `ID must contain 1-256 bytes`; `businessJID must be a user JID`; `limit must be between 1 and 100`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_more_than_100_ids":{"summary":"Empty or more than 100 IDs","value":{"code":400,"error":"provide 1-100 IDs","success":false}},"repeated_id":{"summary":"Repeated ID","value":{"code":400,"error":"duplicate ID","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}},"businessjid_is_not_a_user_jid":{"summary":"businessJID is not a user JID","value":{"code":400,"error":"businessJID must be a user JID","success":false}},"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 100","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"product_missing_from_response":{"summary":"Product missing from response","value":{"code":502,"error":"business operation failed: product list response is missing requested product \"7123456789012346\"","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/catalog/{businessJID}/products/{productID}":{"get":{"tags":["Business"],"summary":"Get one catalog product","description":"Fetches one product from the public catalog of `businessJID` (GraphQL `QueryCatalogProduct`, including compliance information).\n\n**Rules:**\n- `businessJID` must be `@s.whatsapp.net` or `@lid`; `productID` 1-256 bytes\n- `limit` and `cursor` are validated like in paginated reads but not used here\n- Prices are strings in thousandths of the currency\n- Read-only: the catalog cache is not touched\n\n**Visibility:**\n- Hidden products and products still under Meta review are not exposed by public reads: the call returns `502` with GraphQL code `2498052`\n- Use `GET /business/catalog/own` to read your own hidden or pending products\n","parameters":[{"name":"businessJID","in":"path","required":true,"description":"Business owner JID: a phone JID (`@s.whatsapp.net`) or LID (`@lid`). Other servers return `400 businessJID must be a user JID`.","schema":{"type":"string"},"example":"5511988888888@s.whatsapp.net"},{"name":"productID","in":"path","required":true,"description":"Catalog product ID, 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012345"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Catalog product","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"Requested product.","allOf":[{"$ref":"#/components/schemas/BusinessCatalogProduct"}]}}}}}]},"examples":{"approved":{"summary":"Approved product","value":{"code":200,"data":{"data":{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"APPROVED"}},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `ID must contain 1-256 bytes`; `businessJID must be a user JID`; `limit must be between 1 and 100`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}},"businessjid_is_not_a_user_jid":{"summary":"businessJID is not a user JID","value":{"code":400,"error":"businessJID must be a user JID","success":false}},"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 100","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"hidden_or_under_review":{"summary":"Hidden or under review","value":{"code":502,"error":"business operation failed: QueryCatalogProduct: 2498052  (ERROR)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections":{"post":{"tags":["Business"],"summary":"Create a catalog collection","description":"Creates a collection in the own catalog and returns its `id` and `review_status` (collections go through Meta review; observed value `STATUS_APPROVED`).\n\n**Rules:**\n- `name` is required, 1-256 bytes after trimming (`400 name is required (1-256 bytes)`)\n- `product_ids`: unique own product IDs of 1-256 bytes. The gateway accepts 0-100, but WhatsApp requires **1-100** and an empty list returns `502`\n- Products hidden or under review are not listed in public reads of the collection\n- On success this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Collection name and its products.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementCollectionRequest"},"examples":{"minimal":{"summary":"One product","description":"Creates a collection with a single product.","value":{"name":"Chairs","product_ids":["7123456789012345"]}},"several":{"summary":"Several products","description":"Creates a collection with three products.","value":{"name":"Living room","product_ids":["7123456789012345","7123456789012346","7123456789012347"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Collection created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"Created collection.","allOf":[{"$ref":"#/components/schemas/BusinessCollectionMutationResult"}]}}}}}]},"examples":{"pending":{"summary":"Created and pending review","value":{"code":200,"data":{"data":{"id":"7123456789012350","review_status":"STATUS_APPROVED"},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `name is required (1-256 bytes)`; `provide 1-100 IDs`; `duplicate ID`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_long_name":{"summary":"Blank or long name","value":{"code":400,"error":"name is required (1-256 bytes)","success":false}},"more_than_100_ids":{"summary":"More than 100 IDs","value":{"code":400,"error":"provide 1-100 IDs","success":false}},"repeated_id":{"summary":"Repeated ID","value":{"code":400,"error":"duplicate ID","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_product_list":{"summary":"Empty product list","value":{"code":502,"error":"business operation failed: business collection product list must contain between 1 and 100 IDs","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections/delete":{"post":{"tags":["Business"],"summary":"Delete catalog collections","description":"Deletes collections from the own catalog. The products inside them are not deleted.\n\n**Rules:**\n- `collection_ids` is required: 1-100 unique IDs of 1-256 bytes (`400 provide 1-100 IDs`, `duplicate ID`, `ID must contain 1-256 bytes`)\n- Use the latest ID of each collection (edits issue new IDs)\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Collection IDs to delete (1-100 unique).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementCollectionsRequest"},"examples":{"single":{"summary":"Delete one collection","description":"Deletes one collection by its latest ID.","value":{"collection_ids":["7123456789012350"]}},"several":{"summary":"Delete several collections","description":"Deletes two collections in one call.","value":{"collection_ids":["7123456789012350","7123456789012352"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Collections deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"deleted":{"summary":"Collections deleted","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `provide 1-100 IDs`; `duplicate ID`; `ID must contain 1-256 bytes`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_more_than_100_ids":{"summary":"Empty or more than 100 IDs","value":{"code":400,"error":"provide 1-100 IDs","success":false}},"repeated_id":{"summary":"Repeated ID","value":{"code":400,"error":"duplicate ID","success":false}},"blank_or_long_id":{"summary":"Blank or long ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"old_collection_id":{"summary":"Old collection ID","value":{"code":502,"error":"business operation failed: delete business collections: business GraphQL request failed with error code(s) 2498052","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections/reorder":{"post":{"tags":["Business"],"summary":"Reorder catalog collections","description":"Moves collections to new positions in the own catalog (Meta mutation `xfb_whatsapp_catalog_update_collection_list`).\n\n**Current live behavior:**\n- WhatsApp currently rejects this mutation: the route responds `502 business operation failed: reorder business collections: business GraphQL request failed with error code(s) 2498055`\n- The contract below is what the gateway validates and sends\n\n**Rules:**\n- `moves` is required, 1-100 items (`400 provide 1-100 moves`)\n- Each move has `collection_id` (unique across moves, 1-256 bytes), `from_index` and `to_index` (zero-based; negative values return `400 indices must be nonnegative`, values of 100 or more return `502`)\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Moves to apply (1-100).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementMovesRequest"},"examples":{"single":{"summary":"Move one collection to the top","description":"Moves the collection at position 2 to position 0.","value":{"moves":[{"collection_id":"7123456789012352","from_index":2,"to_index":0}]}},"swap":{"summary":"Swap two collections","description":"Exchanges the first two positions.","value":{"moves":[{"collection_id":"7123456789012350","from_index":0,"to_index":1},{"collection_id":"7123456789012352","from_index":1,"to_index":0}]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Collections reordered","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"reordered":{"summary":"Collections reordered","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `provide 1-100 moves`; `indices must be nonnegative`; `duplicate ID`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_more_than_100_moves":{"summary":"Empty or more than 100 moves","value":{"code":400,"error":"provide 1-100 moves","success":false}},"negative_index":{"summary":"Negative index","value":{"code":400,"error":"indices must be nonnegative","success":false}},"repeated_collection":{"summary":"Repeated collection","value":{"code":400,"error":"duplicate ID","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"mutation_rejected_by_whatsapp":{"summary":"Mutation rejected by WhatsApp","value":{"code":502,"error":"business operation failed: reorder business collections: business GraphQL request failed with error code(s) 2498055","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections/{businessJID}/{collectionID}":{"get":{"tags":["Business"],"summary":"Get one catalog collection with its products","description":"Fetches one collection from the public catalog of `businessJID` (GraphQL `QueryProductSingleCollection`) with a page of its products.\n\n**Features:**\n- Collection `id`, `name`, review `status_info` (`status`, `can_appeal`, `commerce_url`, `reject_reason` when present)\n- One page of products; pass `next` as the next `cursor`\n\n**Rules:**\n- `businessJID` must be `@s.whatsapp.net` or `@lid`; `collectionID` 1-256 bytes\n- `limit` 1-100 (default 20); `cursor` at most 2048 bytes\n- Products hidden or under review are not listed\n- Editing a collection issues a NEW ID; the previous ID stops resolving and returns `502` with GraphQL `2498052`\n- Read-only: the catalog cache is not touched\n","parameters":[{"name":"businessJID","in":"path","required":true,"description":"Business owner JID: a phone JID (`@s.whatsapp.net`) or LID (`@lid`). Other servers return `400 businessJID must be a user JID`.","schema":{"type":"string"},"example":"5511988888888@s.whatsapp.net"},{"name":"collectionID","in":"path","required":true,"description":"Collection ID, 1-256 bytes. Use the latest ID returned by create/update.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012350"},{"name":"limit","in":"query","required":false,"description":"Page size, 1-100 (default 20). Must appear at most once.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"example":20},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor copied from `next` of the previous page. At most once and 2048 bytes.","schema":{"type":"string","maxLength":2048},"example":"AQHRcursorEXAMPLE"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Collection page","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Collection with one page of products.","properties":{"id":{"type":"string","description":"Collection ID.","example":"7123456789012350"},"name":{"type":"string","description":"Collection name.","example":"Chairs"},"next":{"type":"string","description":"Cursor for the next page of products; omitted on the last page.","example":"AQHRcursorEXAMPLE"},"previous":{"type":"string","description":"Cursor for the previous page, when present.","example":"AQHRcursorPREVIOUS"},"products":{"type":"array","description":"Products on this page.","items":{"$ref":"#/components/schemas/BusinessCatalogProduct"}},"status_info":{"type":"object","description":"Meta review state of the collection.","properties":{"status":{"type":"string","description":"Review status.","example":"APPROVED"},"can_appeal":{"type":"boolean","description":"True when a rejected collection can be appealed.","example":false},"commerce_url":{"type":"string","description":"Commerce policy link, when present.","example":"https://www.facebook.com/policies/commerce"},"reject_reason":{"type":"string","description":"Rejection reason, when rejected.","example":"POLICY_VIOLATION"}}}}}}}}}]},"examples":{"approved":{"summary":"Approved collection with one product","value":{"code":200,"data":{"data":{"id":"7123456789012350","name":"Chairs","next":"AQHRcursorEXAMPLE","products":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"APPROVED"}}],"status_info":{"status":"APPROVED"}},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `ID must contain 1-256 bytes`; `businessJID must be a user JID`; `limit must be between 1 and 100`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}},"businessjid_is_not_a_user_jid":{"summary":"businessJID is not a user JID","value":{"code":400,"error":"businessJID must be a user JID","success":false}},"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 100","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"old_or_unknown_collection_id":{"summary":"Old or unknown collection ID","value":{"code":502,"error":"business operation failed: QueryProductSingleCollection: 2498052  (ERROR)","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections/{collectionID}":{"put":{"tags":["Business"],"summary":"Edit a catalog collection","description":"Edits a collection of the own catalog: rename it and/or add and remove products.\n\n**Versioning:**\n- A successful edit returns a NEW `id` in `data.data.id`; use it from then on\n- The previous ID stops resolving (`GET /business/collections/{businessJID}/{oldId}` returns `502` with GraphQL `2498052`)\n- The edited collection is reviewed by Meta again (`review_status`)\n\n**Rules:**\n- At least one of `name`, `add_product_ids`, `remove_product_ids` (`400 collection update is empty`)\n- `name`, when present, 1-256 bytes; omit it to keep the current name\n- `add_product_ids` / `remove_product_ids`: each 0-100 unique IDs of 1-256 bytes\n- The same ID in both lists returns `502 business operation failed: product ID \"<id>\" cannot be added and removed together`\n- On success this user's catalog cache is cleared\n","parameters":[{"name":"collectionID","in":"path","required":true,"description":"Current collection ID (the latest one returned by create/update), 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012350"}],"requestBody":{"required":true,"description":"Fields to change; at least one is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/types.BusinessCollectionUpdate"},"examples":{"rename":{"summary":"Rename only","description":"Changes the name and keeps the products.","value":{"name":"Dining chairs"}},"products":{"summary":"Add and remove products","description":"Swaps one product for another.","value":{"add_product_ids":["7123456789012346"],"remove_product_ids":["7123456789012345"]}},"full":{"summary":"Rename and add products","description":"Renames the collection and adds two products.","value":{"name":"Dining chairs","add_product_ids":["7123456789012346","7123456789012347"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Collection edited (new ID)","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"New collection ID and review status.","allOf":[{"$ref":"#/components/schemas/BusinessCollectionMutationResult"}]}}}}}]},"examples":{"new_id":{"summary":"New collection ID after the edit","value":{"code":200,"data":{"data":{"id":"7123456789012351","review_status":"STATUS_APPROVED"},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `collection update is empty`; `provide 1-100 IDs`; `duplicate ID`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`; `ID must contain 1-256 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"nothing_to_change":{"summary":"Nothing to change","value":{"code":400,"error":"collection update is empty","success":false}},"more_than_100_ids":{"summary":"More than 100 IDs","value":{"code":400,"error":"provide 1-100 IDs","success":false}},"repeated_id":{"summary":"Repeated ID","value":{"code":400,"error":"duplicate ID","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"same_id_added_and_removed":{"summary":"Same ID added and removed","value":{"code":502,"error":"business operation failed: product ID \"7123456789012345\" cannot be added and removed together","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/collections/{collectionID}/appeal":{"post":{"tags":["Business"],"summary":"Appeal a collection review decision","description":"Requests a new Meta review of an own collection, typically one rejected in review (`status_info.can_appeal: true`, `reject_reason`).\n\n**Rules:**\n- `reason` is required, non-blank and at most 1024 bytes (`400 reason must contain 1-1024 bytes`); it is trimmed before sending\n- Use the latest collection ID (edits issue new IDs)\n- Upstream refusals return `502`\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","parameters":[{"name":"collectionID","in":"path","required":true,"description":"Own collection ID (latest version), 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012350"}],"requestBody":{"required":true,"description":"Appeal reason shown to the Meta reviewer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementAppealRequest"},"examples":{"reason":{"summary":"Appeal reason","description":"Explains why the collection complies with the commerce policies.","value":{"reason":"The collection only groups handmade furniture that complies with the commerce policies."}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Appeal submitted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"submitted":{"summary":"Appeal accepted","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `reason must contain 1-1024 bytes`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`; `ID must contain 1-256 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_long_reason":{"summary":"Blank or long reason","value":{"code":400,"error":"reason must contain 1-1024 bytes","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"collection_cannot_be_appealed":{"summary":"Collection cannot be appealed","value":{"code":502,"error":"business operation failed: appeal business collection: business GraphQL request failed with error code(s) 2498052","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/cover":{"post":{"tags":["Business"],"summary":"Set the business cover photo","description":"Uploads a JPEG or PNG image and sets it as the cover photo of the connected business profile. Returns `data.data.cover_id`, used later by `DELETE /business/cover/{coverID}`.\n\n**Rules:**\n- `image` is required, standard base64 of the raw bytes without a `data:` URI prefix\n- The gateway accepts 1 byte to 16 MiB of JPEG/PNG (`400 image must contain 1-16777216 bytes` / `image must be JPEG or PNG`), but WhatsApp's library limits cover photos to **5 MiB**: larger images return `502`\n- Do not retry blindly after a `5xx`: the upload may already have been accepted\n- On success this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Cover photo bytes in standard base64 (up to 5 MiB accepted by WhatsApp).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementImageRequest"},"examples":{"png":{"summary":"PNG image","description":"A 1x1 PNG encoded in base64 (replace with the real cover photo).","value":{"image":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Cover photo set","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Cover photo reference.","properties":{"cover_id":{"type":"string","description":"Cover photo ID for `DELETE /business/cover/{coverID}`.","example":"7123456789012348"}}}}}}}]},"examples":{"set":{"summary":"Cover photo ID","value":{"code":200,"data":{"data":{"cover_id":"7123456789012348"},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `image must contain 1-16777216 bytes`; `image must be JPEG or PNG`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_larger_than_16_mib":{"summary":"Empty or larger than 16 MiB","value":{"code":400,"error":"image must contain 1-16777216 bytes","success":false}},"not_jpeg_or_png":{"summary":"Not JPEG or PNG","value":{"code":400,"error":"image must be JPEG or PNG","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"larger_than_5_mib":{"summary":"Larger than 5 MiB","value":{"code":502,"error":"business operation failed: business cover photo exceeds 5242880 bytes","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/cover/{coverID}":{"delete":{"tags":["Business"],"summary":"Delete the business cover photo","description":"Removes the cover photo of the connected business profile (IQ `business_profile` / `cover_photo op=delete`).\n\n**Rules:**\n- `coverID` is the `cover_id` returned by `POST /business/cover`, 1-256 bytes (`400 ID must contain 1-256 bytes`)\n- No body is read\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","parameters":[{"name":"coverID","in":"path","required":true,"description":"Cover photo ID (`cover_id` from `POST /business/cover`), 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012348"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Cover photo deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"deleted":{"summary":"Cover photo removed","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `ID must contain 1-256 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unknown_cover_id":{"summary":"Unknown cover ID","value":{"code":502,"error":"business operation failed: failed to delete business cover photo: info query returned status 404: item-not-found","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/eligibility":{"post":{"tags":["Business"],"summary":"Check business feature eligibility","description":"Asks WhatsApp whether the connected business account is eligible for the requested features (IQ `features`).\n\n**Features:**\n- Checks up to 6 features in one call: `meta_verified`, `marketing_messages`, `genai`, `genai_image`, `meta_one`, `bb_pro`\n- Returns one entry per feature with `status` and, when sent by the server, `expiration`, `additional_params`, `show_privacy_interstitial_to_new_users` and `v1_enabled`\n\n**Rules:**\n- `features` is required: 1-6 known values (`400 provide 1-6 features` / `unknown business feature`)\n- Duplicated features pass the gateway but WhatsApp's library refuses them with `502 business operation failed: duplicate business feature \"<name>\"`\n- Accepted statuses: `marketing_messages` → `FAIL`, `PAUSED`, `SUCCESS`, `WARNING`; `bb_pro` → `ELIGIBLE_TO_ONBOARD`, `NOT_ELIGIBLE`, `ONBOARDED`; other features → `FAIL`, `SUCCESS`. Any other status fails with `502`\n- Read-only: the catalog cache is not touched\n","requestBody":{"required":true,"description":"Features to check (1-6 known values).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementEligibilityRequest"},"examples":{"one":{"summary":"Single feature","description":"Check only Meta Verified eligibility.","value":{"features":["meta_verified"]}},"all":{"summary":"All features","description":"Check every supported feature in one call.","value":{"features":["meta_verified","marketing_messages","genai","genai_image","meta_one","bb_pro"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Eligibility per requested feature","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Eligibility result.","properties":{"features":{"type":"array","description":"One entry per requested feature.","items":{"type":"object","properties":{"feature":{"type":"string","description":"Feature name.","example":"meta_verified"},"status":{"type":"string","description":"Eligibility status for this feature.","example":"SUCCESS"},"expiration":{"type":"integer","description":"Expiration as a Unix timestamp, when sent.","example":1767225600},"additional_params":{"type":"string","description":"Opaque extra parameters, when sent.","example":"{}"},"show_privacy_interstitial_to_new_users":{"type":"boolean","description":"Privacy interstitial flag, when sent.","example":false},"v1_enabled":{"type":"boolean","description":"Version flag, when sent.","example":true}}}}}}}}}}]},"examples":{"mixed":{"summary":"Two features checked","value":{"code":200,"data":{"data":{"features":[{"feature":"meta_verified","status":"SUCCESS"},{"feature":"bb_pro","status":"ELIGIBLE_TO_ONBOARD"}]},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `provide 1-6 features`; `unknown business feature`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_features_or_more_than_6":{"summary":"No features or more than 6","value":{"code":400,"error":"provide 1-6 features","success":false}},"unknown_feature":{"summary":"Unknown feature","value":{"code":400,"error":"unknown business feature","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"duplicated_feature":{"summary":"Duplicated feature","value":{"code":502,"error":"business operation failed: duplicate business feature \"genai\"","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/linked-accounts":{"get":{"tags":["Business"],"summary":"Get Meta accounts linked to the business","description":"Returns the Meta assets linked to the connected WhatsApp Business account (IQ `linked_accounts`).\n\n**Features:**\n- `facebook_page`: page ID, name, picture, ad flags and whether it is shown on the profile\n- `facebook_business`: business portfolio with `catalog_id` / `catalog_state` when a catalog is attached\n- `instagram_professional`: handle, name, picture and profile visibility\n- `whatsapp_ad_identity`: ad identity ID and ad flags\n\n**Rules:**\n- No body and no query parameters\n- Each key is omitted when the asset is not linked, so an account without links returns `data.data: {}`\n- Read-only: the catalog cache is not touched\n\n**Use Cases:**\n- Check whether a Facebook page or Instagram account is connected before running click-to-WhatsApp ads\n- Find the Meta catalog ID attached to the business portfolio\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Linked Meta assets","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Linked assets; keys are omitted when not linked.","properties":{"facebook_page":{"type":"object","description":"Linked Facebook page.","properties":{"id":{"type":"string","description":"Page ID.","example":"7123456789012360"},"display_name":{"type":"string","description":"Page name.","example":"Example Store"},"profile_sync":{"type":"string","description":"Profile sync state, when reported.","example":"ENABLED"},"has_active_ctwa_ad":{"type":"boolean","description":"True when a click-to-WhatsApp ad is running.","example":false},"has_created_ad":{"type":"boolean","description":"True when an ad was ever created.","example":false},"profile_picture_url":{"type":"string","description":"Page picture URL.","example":"https://example.com/page-picture.jpg"},"show_on_profile":{"type":"boolean","description":"True when shown on the WhatsApp profile.","example":true},"whatsapp_as_page_button":{"type":"boolean","description":"True when the page uses WhatsApp as its button.","example":false}}},"facebook_business":{"type":"object","description":"Linked business portfolio.","properties":{"id":{"type":"string","description":"Business portfolio ID.","example":"7123456789012361"},"display_name":{"type":"string","description":"Portfolio name.","example":"Example Store"},"catalog_id":{"type":"string","description":"Attached catalog ID, when present.","example":"7123456789012300"},"catalog_state":{"type":"string","description":"Catalog state, when present.","example":"ACTIVE"}}},"instagram_professional":{"type":"object","description":"Linked Instagram professional account.","properties":{"handle":{"type":"string","description":"Instagram handle.","example":"examplestore"},"display_name":{"type":"string","description":"Account name.","example":"Example Store"},"profile_picture_url":{"type":"string","description":"Picture URL.","example":"https://example.com/instagram-picture.jpg"},"show_on_profile":{"type":"boolean","description":"True when shown on the WhatsApp profile.","example":true}}},"whatsapp_ad_identity":{"type":"object","description":"WhatsApp ad identity.","properties":{"id":{"type":"string","description":"Ad identity ID.","example":"7123456789012362"},"has_active_ctwa_ad":{"type":"boolean","description":"True when a click-to-WhatsApp ad is running.","example":false},"has_created_ad":{"type":"boolean","description":"True when an ad was ever created.","example":true}}}}}}}}}]},"examples":{"page_and_instagram":{"summary":"Facebook page and Instagram linked","value":{"code":200,"data":{"data":{"facebook_page":{"id":"7123456789012360","display_name":"Example Store","has_active_ctwa_ad":false,"has_created_ad":false,"profile_picture_url":"https://example.com/page-picture.jpg","show_on_profile":true,"whatsapp_as_page_button":false},"instagram_professional":{"handle":"examplestore","display_name":"Example Store","profile_picture_url":"https://example.com/instagram-picture.jpg","show_on_profile":true}},"success":true},"success":true}},"no_links":{"summary":"No linked assets","value":{"code":200,"data":{"data":{},"success":true},"success":true}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"iq_failed":{"summary":"IQ failed","value":{"code":502,"error":"business operation failed: get linked business accounts: info query timed out","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/merchant-compliance":{"get":{"tags":["Business"],"summary":"Get merchant compliance information","description":"Reads the merchant compliance record of the connected business account, as shown in the WhatsApp Business compliance settings.\n\n**Features:**\n- Legal entity name and type, registration flag\n- Customer care contact and grievance officer\n\n**Rules:**\n- No body; uses the Meta GraphQL endpoint\n- If the server response has no `merchant_info` the call fails with `502`\n- Read-only: the catalog cache is not touched\n","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Merchant compliance record","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"Merchant compliance record.","allOf":[{"$ref":"#/components/schemas/types.BusinessMerchantCompliance"}]}}}}}]},"examples":{"registered_company":{"summary":"Registered private company","value":{"code":200,"data":{"data":{"entity_name":"Example Store Ltd","entity_type":"PRIVATE_COMPANY","is_registered":true,"entity_type_custom":"","customer_care_details":{"email":"support@example.com","landline_number":"","mobile_number":"5511999999999"},"grievance_officer_details":{"name":"Jane Doe","email":"compliance@example.com","landline_number":"","mobile_number":"5511988888888"}},"success":true},"success":true}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"response_without_merchant_info":{"summary":"Response without merchant_info","value":{"code":502,"error":"business operation failed: business merchant compliance response is missing merchant_info","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}},"put":{"tags":["Business"],"summary":"Set merchant compliance information","description":"Replaces the merchant compliance record of the connected business account and returns the record stored by the server.\n\n**Rules:**\n- `entity_name` is required, 1-256 bytes after trimming; the gateway reports a blank or oversized value as `400 ID must contain 1-256 bytes`\n- `entity_type` is required: `SOLE_PROPRIETORSHIP`, `PARTNERSHIP`, `PRIVATE_COMPANY`, `PUBLIC_COMPANY`, `LIMITED_LIABILITY_PARTNERSHIP` or `OTHER`; `OTHER` requires `entity_type_custom`\n- Limits: names 256 bytes, emails 254 bytes, phone numbers 64 bytes; all strings are trimmed\n- The whole object is sent: omitted nested fields are sent as empty strings\n- Library validation (missing or unsupported `entity_type`, missing custom type, lengths) returns `502 business operation failed: business merchant …`\n- On success this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Complete merchant compliance record.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/types.BusinessMerchantCompliance"},"examples":{"company":{"summary":"Registered private company","description":"Private company with customer care and grievance officer contacts.","value":{"entity_name":"Example Store Ltd","entity_type":"PRIVATE_COMPANY","is_registered":true,"customer_care_details":{"email":"support@example.com","landline_number":"","mobile_number":"5511999999999"},"grievance_officer_details":{"name":"Jane Doe","email":"compliance@example.com","landline_number":"","mobile_number":"5511988888888"}}},"other":{"summary":"Custom entity type (OTHER)","description":"Unregistered cooperative using `entity_type_custom`.","value":{"entity_name":"Example Cooperative","entity_type":"OTHER","is_registered":false,"entity_type_custom":"Cooperative","customer_care_details":{"email":"support@example.com","landline_number":"","mobile_number":"5511999999999"},"grievance_officer_details":{"name":"Jane Doe","email":"compliance@example.com","landline_number":"","mobile_number":"5511988888888"}}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Stored merchant compliance record","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"Merchant compliance record.","allOf":[{"$ref":"#/components/schemas/types.BusinessMerchantCompliance"}]}}}}}]},"examples":{"stored":{"summary":"Record stored by the server","value":{"code":200,"data":{"data":{"entity_name":"Example Store Ltd","entity_type":"PRIVATE_COMPANY","is_registered":true,"entity_type_custom":"","customer_care_details":{"email":"support@example.com","landline_number":"","mobile_number":"5511999999999"},"grievance_officer_details":{"name":"Jane Doe","email":"compliance@example.com","landline_number":"","mobile_number":"5511988888888"}},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `ID must contain 1-256 bytes`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_long_entity_name":{"summary":"Blank or long entity_name","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unsupported_entity_type":{"summary":"Unsupported entity type","value":{"code":502,"error":"business operation failed: unsupported business merchant entity type \"LLC\"","success":false}},"other_without_custom_type":{"summary":"OTHER without custom type","value":{"code":502,"error":"business operation failed: business merchant custom entity type is empty","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products":{"post":{"tags":["Business"],"summary":"Create a catalog product","description":"Creates a product in the own catalog of the connected session and returns it in `data.data` with its new `id`.\n\n**Price and currency:**\n- `price` and `sale_price` are strings with integer thousandths of the currency, no separators: `\"3000000\"` = 3,000.00; `\"2499900\"` = 2,499.90\n- `currency` (ISO-4217 uppercase) is required with `price`; `currency` or `sale_price` without `price` returns `502`\n\n**Media:**\n- `image_urls`: 1-10 HTTPS WhatsApp/Meta media URLs, normally the `image_id` returned by `POST /business/products/image`; the first one is the main photo\n- Other hosts return `502 business operation failed: invalid business product image URL: …`\n\n**Country of origin:**\n- Optional in the API. Send `compliance_info.country_code_origin` (ISO-3166 alpha-2) with optional `importer_name` / `importer_address`\n- When it does not apply, send `compliance_category: \"COUNTRY_ORIGIN_EXEMPT\"` without `compliance_info` (\"Not applicable\" in the app)\n\n**Validation:**\n- Gateway `400`: `product.name` blank or over 256 bytes, `width`/`height` outside 0 or 1-1024, `image_urls` count outside 1-10, unknown fields (also inside `product`)\n- WhatsApp library `502`: media hosts, `url` not absolute HTTPS ≤ 2048 bytes, price/currency format, `description` > 4096 bytes, `retailer_id` > 256 bytes, more than 10 `video_urls`, compliance field lengths\n\n**Review:**\n- Created or edited products go through Meta review (`status_info.status`: `NO_REVIEW`, `PENDING`, `APPROVED`, `REJECTED`)\n- While pending or hidden the product is missing from public reads and collections; `GET /business/catalog/own` shows it\n\n**Behavior:**\n- `is_hidden: true` creates the product already hidden\n- `width` / `height` only size the media URLs returned in the response (default 100)\n- On success this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Product to create plus optional response media size.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementProductRequest"},"examples":{"with_country_of_origin":{"summary":"Product with sale price and country of origin","description":"Full product: price, sale price, retailer ID, one uploaded photo and country of origin.","value":{"product":{"name":"Wooden chair","description":"Solid wood chair with natural finish.","url":"https://example.com/products/chair","retailer_id":"CHAIR-001","currency":"BRL","price":"3000000","sale_price":"2499900","is_hidden":false,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"compliance_info":{"country_code_origin":"BR"}}}},"country_exempt":{"summary":"Country of origin not applicable","description":"Service product using `COUNTRY_ORIGIN_EXEMPT` without `compliance_info`.","value":{"product":{"name":"Assembly service","currency":"BRL","price":"150000","is_hidden":false,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"compliance_category":"COUNTRY_ORIGIN_EXEMPT"}}},"hidden_draft":{"summary":"Hidden draft without price","description":"Creates a hidden product without price; `currency` must also be omitted.","value":{"product":{"name":"Oak table (draft)","is_hidden":true,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"]},"width":640,"height":640}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Product created","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"Created product (review usually `PENDING`).","allOf":[{"$ref":"#/components/schemas/BusinessCatalogProduct"}]}}}}}]},"examples":{"pending_review":{"summary":"Created and pending review","value":{"code":200,"data":{"data":{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"PENDING"}},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `product name must contain 1-256 bytes`; `dimensions must be 0 (default) or 1-1024`; `product requires 1-10 images`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_long_name":{"summary":"Blank or long name","value":{"code":400,"error":"product name must contain 1-256 bytes","success":false}},"invalid_media_size":{"summary":"Invalid media size","value":{"code":400,"error":"dimensions must be 0 (default) or 1-1024","success":false}},"no_images_or_more_than_10":{"summary":"No images or more than 10","value":{"code":400,"error":"product requires 1-10 images","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"image_host_not_allowed":{"summary":"Image host not allowed","value":{"code":502,"error":"business operation failed: invalid business product image URL: URL must use a WhatsApp or Meta media host","success":false}},"price_without_currency":{"summary":"Price without currency","value":{"code":502,"error":"business operation failed: business product currency must be a three-letter uppercase code","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products/delete":{"post":{"tags":["Business"],"summary":"Delete catalog products","description":"Deletes products from the own catalog in one call. Deletion is not reversible.\n\n**Rules:**\n- `product_ids` is required: 1-100 unique IDs of 1-256 bytes (`400 provide 1-100 IDs`, `duplicate ID`, `ID must contain 1-256 bytes`)\n- `data.data.deleted` is the number the server reports as deleted; it can be lower than the IDs sent (for example IDs that no longer exist)\n- On success this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Own product IDs to delete (1-100 unique).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementIDsRequest"},"examples":{"single":{"summary":"Delete one product","description":"Removes a single product.","value":{"product_ids":["7123456789012345"]}},"several":{"summary":"Delete several products","description":"Removes two products in one call.","value":{"product_ids":["7123456789012345","7123456789012346"]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Products deleted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Deletion count.","properties":{"deleted":{"type":"integer","description":"Number of products the server reports as deleted.","example":2}}}}}}}]},"examples":{"two_deleted":{"summary":"Two products deleted","value":{"code":200,"data":{"data":{"deleted":2},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `provide 1-100 IDs`; `duplicate ID`; `ID must contain 1-256 bytes`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_more_than_100_ids":{"summary":"Empty or more than 100 IDs","value":{"code":400,"error":"provide 1-100 IDs","success":false}},"repeated_id":{"summary":"Repeated ID","value":{"code":400,"error":"duplicate ID","success":false}},"blank_or_long_id":{"summary":"Blank or long ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"graphql_request_timed_out":{"summary":"GraphQL request timed out","value":{"code":502,"error":"business operation failed: delete business products: execute business GraphQL request: context deadline exceeded","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products/image":{"post":{"tags":["Business"],"summary":"Upload a catalog product image","description":"Uploads one JPEG or PNG photo and returns `data.data.image_id`, the HTTPS media URL to use in `image_urls` of `POST /business/products` and `PUT /business/products/{productID}`.\n\n**Rules:**\n- `image` is standard base64 of the raw bytes, without a `data:` URI prefix (a prefix makes JSON decoding fail with `400`)\n- Empty, larger than 16 MiB or not JPEG/PNG → `400`\n- Send one call per photo; do not retry automatically after an uncertain `5xx`, the upload may have been accepted\n- On success this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Photo bytes in standard base64.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementImageRequest"},"examples":{"png":{"summary":"PNG image","description":"A 1x1 PNG encoded in base64 (replace with the real photo).","value":{"image":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Image uploaded","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Uploaded media reference.","properties":{"image_id":{"type":"string","description":"HTTPS media URL to use in `image_urls`.","example":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}}}}}}}]},"examples":{"uploaded":{"summary":"Uploaded photo URL","value":{"code":200,"data":{"data":{"image_id":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `image must contain 1-16777216 bytes`; `image must be JPEG or PNG`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"empty_or_larger_than_16_mib":{"summary":"Empty or larger than 16 MiB","value":{"code":400,"error":"image must contain 1-16777216 bytes","success":false}},"not_jpeg_or_png":{"summary":"Not JPEG or PNG","value":{"code":400,"error":"image must be JPEG or PNG","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"upload_host_unavailable":{"summary":"Upload host unavailable","value":{"code":502,"error":"business operation failed: media connection response contained no upload hosts","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products/{productID}":{"put":{"tags":["Business"],"summary":"Replace a catalog product","description":"Replaces a product of the own catalog and returns the updated product in `data.data`.\n\n**Replace semantics:**\n- The PUT replaces `product_info` entirely: every omitted field is REMOVED (no `sale_price` removes the sale price; no `compliance_info` removes the country of origin)\n- `is_hidden` is always sent, so omitting it makes the product visible\n- Read the product first with `GET /business/catalog/own` and send it complete\n- On read the server normalizes `url` with a trailing slash\n\n**Price and currency:**\n- `price` and `sale_price` are strings with integer thousandths of the currency, no separators: `\"3000000\"` = 3,000.00; `\"2499900\"` = 2,499.90\n- `currency` (ISO-4217 uppercase) is required with `price`; `currency` or `sale_price` without `price` returns `502`\n\n**Media:**\n- `image_urls`: 1-10 HTTPS WhatsApp/Meta media URLs, normally the `image_id` returned by `POST /business/products/image`; the first one is the main photo\n- Other hosts return `502 business operation failed: invalid business product image URL: …`\n\n**Country of origin:**\n- Optional in the API. Send `compliance_info.country_code_origin` (ISO-3166 alpha-2) with optional `importer_name` / `importer_address`\n- When it does not apply, send `compliance_category: \"COUNTRY_ORIGIN_EXEMPT\"` without `compliance_info` (\"Not applicable\" in the app)\n\n**Validation:**\n- Gateway `400`: `product.name` blank or over 256 bytes, `width`/`height` outside 0 or 1-1024, `image_urls` count outside 1-10, unknown fields (also inside `product`)\n- WhatsApp library `502`: media hosts, `url` not absolute HTTPS ≤ 2048 bytes, price/currency format, `description` > 4096 bytes, `retailer_id` > 256 bytes, more than 10 `video_urls`, compliance field lengths\n\n**Review:**\n- Created or edited products go through Meta review (`status_info.status`: `NO_REVIEW`, `PENDING`, `APPROVED`, `REJECTED`)\n- While pending or hidden the product is missing from public reads and collections; `GET /business/catalog/own` shows it\n\n**Behavior:**\n- On success this user's catalog cache is cleared\n","parameters":[{"name":"productID","in":"path","required":true,"description":"ID of the own catalog product to replace, 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012345"}],"requestBody":{"required":true,"description":"Complete product; omitted fields are removed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementProductRequest"},"examples":{"full_replace":{"summary":"Complete product","description":"Sends every field so nothing is removed.","value":{"product":{"name":"Wooden chair","description":"Solid wood chair with natural finish.","url":"https://example.com/products/chair","retailer_id":"CHAIR-001","currency":"BRL","price":"3000000","sale_price":"2499900","is_hidden":false,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"compliance_info":{"country_code_origin":"BR"}}}},"remove_sale_price":{"summary":"Remove the sale price","description":"Same product without `sale_price`: the sale price is removed.","value":{"product":{"name":"Wooden chair","description":"Solid wood chair with natural finish.","url":"https://example.com/products/chair","retailer_id":"CHAIR-001","currency":"BRL","price":"3000000","is_hidden":false,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"compliance_info":{"country_code_origin":"BR"}}}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Product replaced","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"description":"Updated product.","allOf":[{"$ref":"#/components/schemas/BusinessCatalogProduct"}]}}}}}]},"examples":{"updated":{"summary":"Product after the edit","value":{"code":200,"data":{"data":{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"PENDING"}},"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `product name must contain 1-256 bytes`; `dimensions must be 0 (default) or 1-1024`; `product requires 1-10 images`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`; `ID must contain 1-256 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_long_name":{"summary":"Blank or long name","value":{"code":400,"error":"product name must contain 1-256 bytes","success":false}},"invalid_media_size":{"summary":"Invalid media size","value":{"code":400,"error":"dimensions must be 0 (default) or 1-1024","success":false}},"no_images_or_more_than_10":{"summary":"No images or more than 10","value":{"code":400,"error":"product requires 1-10 images","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"image_host_not_allowed":{"summary":"Image host not allowed","value":{"code":502,"error":"business operation failed: invalid business product image URL: URL must use a WhatsApp or Meta media host","success":false}},"price_without_currency":{"summary":"Price without currency","value":{"code":502,"error":"business operation failed: business product currency must be a three-letter uppercase code","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products/{productID}/appeal":{"post":{"tags":["Business"],"summary":"Appeal a product review decision","description":"Requests a new Meta review of an own catalog product, typically one rejected in review (`status_info.status: REJECTED`, `status_info.can_appeal: true`).\n\n**Rules:**\n- `reason` is required, non-blank and at most 1024 bytes (`400 reason must contain 1-1024 bytes`); it is trimmed before sending\n- Upstream refusals (for example a product that cannot be appealed) return `502`\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","parameters":[{"name":"productID","in":"path","required":true,"description":"Own catalog product ID, 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012345"}],"requestBody":{"required":true,"description":"Appeal reason shown to the Meta reviewer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementAppealRequest"},"examples":{"reason":{"summary":"Appeal reason","description":"Explains why the product complies with the commerce policies.","value":{"reason":"The product is a handmade wooden chair and complies with the commerce policies."}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Appeal submitted","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"submitted":{"summary":"Appeal accepted","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `reason must contain 1-1024 bytes`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`; `ID must contain 1-256 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"blank_or_long_reason":{"summary":"Blank or long reason","value":{"code":400,"error":"reason must contain 1-1024 bytes","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"product_cannot_be_appealed":{"summary":"Product cannot be appealed","value":{"code":502,"error":"business operation failed: appeal business product: business GraphQL request failed with error code(s) 2498052","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/products/{productID}/visibility":{"put":{"tags":["Business"],"summary":"Hide or show a catalog product","description":"Changes only the visibility of an own catalog product, without replacing its other fields.\n\n**Rules:**\n- `hidden` is required (`400 hidden is required`)\n- Hidden products are not exposed by public catalog reads (GraphQL `2498052`) but remain in `GET /business/catalog/own`\n- On success `data.data` is `null` and this user's catalog cache is cleared\n","parameters":[{"name":"productID","in":"path","required":true,"description":"Own catalog product ID, 1-256 bytes.","schema":{"type":"string","minLength":1,"maxLength":256},"example":"7123456789012345"}],"requestBody":{"required":true,"description":"Target visibility.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessManagementHiddenRequest"},"examples":{"hide":{"summary":"Hide product","description":"Removes the product from public catalog reads.","value":{"hidden":true}},"show":{"summary":"Show product","description":"Makes the product visible again.","value":{"hidden":false}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Visibility updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"updated":{"summary":"Visibility changed","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `hidden is required`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`; `ID must contain 1-256 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"hidden_missing":{"summary":"hidden missing","value":{"code":400,"error":"hidden is required","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"blank_or_oversized_path_id":{"summary":"Blank or oversized path ID","value":{"code":400,"error":"ID must contain 1-256 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unknown_or_deleted_product":{"summary":"Unknown or deleted product","value":{"code":502,"error":"business operation failed: update business product visibility: business GraphQL request failed with error code(s) 2498052","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/profile":{"put":{"tags":["Business"],"summary":"Update business profile fields","description":"Applies a partial update to the connected business profile: address, email, description, websites and business hours.\n\n**Rules:**\n- At least one field is required (`400 profile update is empty`); omitted or `null` fields stay unchanged\n- `address` ≤ 512 bytes; `description` ≤ 1024 bytes\n- `email` ≤ 320 bytes, plain address (`user@example.com`); an empty string clears it\n- `websites`: at most 2 absolute `http`/`https` URLs of ≤ 2048 bytes; `[]` clears them\n- `hours`: `timeZone` (IANA) and up to 7 unique `days` (`sun`…`sat`) with `mode` `specific_hours`, `open_24h` or `appointment_only`; `openTime`/`closeTime` are minutes after midnight (0-1439, different) and only valid with `specific_hours`\n- Keys match case-insensitively (`address` or `Address`); snake_case variants such as `time_zone` are unknown fields and return `400`\n- Library validation failures return `502`; on success `data.data` is `null` and this user's catalog cache is cleared\n","requestBody":{"required":true,"description":"Profile fields to change; at least one is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/types.BusinessProfileUpdate"},"examples":{"contact":{"summary":"Contact fields","description":"Updates address, email, description and website.","value":{"address":"100 Example Street, Springfield, IL","email":"contact@example.com","description":"Handmade wooden furniture.","websites":["https://example.com"]}},"hours":{"summary":"Business hours only","description":"Weekday hours, Saturday by appointment and Sunday open 24 hours.","value":{"hours":{"timeZone":"America/Sao_Paulo","days":[{"dayOfWeek":"mon","mode":"specific_hours","openTime":540,"closeTime":1080},{"dayOfWeek":"sat","mode":"appointment_only"},{"dayOfWeek":"sun","mode":"open_24h"}]}}},"clear":{"summary":"Clear email and websites","description":"An empty email and an empty website list remove both.","value":{"email":"","websites":[]}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Profile updated","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","nullable":true,"description":"Always `null`: the operation returns no payload.","example":null}}}}}]},"examples":{"updated":{"summary":"Profile fields applied","value":{"code":200,"data":{"data":null,"success":true},"success":true}}}}}},"400":{"description":"Request rejected before contacting WhatsApp: `profile update is empty`; `invalid JSON body (maximum 24 MiB)`; `JSON object is required`; `exactly one JSON object is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_field_sent":{"summary":"No field sent","value":{"code":400,"error":"profile update is empty","success":false}},"malformed_or_unknown_field":{"summary":"Malformed or unknown field","value":{"code":400,"error":"invalid JSON body (maximum 24 MiB)","success":false}},"json_null_instead_of_an_object":{"summary":"JSON null instead of an object","value":{"code":400,"error":"JSON object is required","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"exactly one JSON object is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"WhatsApp rejected the operation or its response failed validation. The upstream reason follows the `business operation failed:` prefix.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"update_rejected":{"summary":"Update rejected","value":{"code":502,"error":"business operation failed: failed to update business profile: info query returned status 400: bad-request","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/chat/retry/message":{"post":{"tags":["Chat"],"summary":"Ask the phone to resend a message","description":"Asks the **primary phone** to resend a message that this linked device could not decrypt or process (for example after an `UndecryptableMessage` event).\n\nThe gateway sends a peer `PLACEHOLDER_MESSAGE_RESEND` request to its own account. If the phone still has the message it re-delivers it, and the recovered content arrives **asynchronously** as a normal `Message` event through the webhook and transports.\n\n**Rules:**\n- `MessageID` and `ChatJID` are required; keys are case-insensitive, so `messageId`, `chatJid`, `senderJid`, `retryType` and `forceRetry` also work.\n- `SenderJID` (the participant in groups) is required unless `ForceRetry` is `true`; without either the request fails with **500**.\n- `RetryType` is `incoming` (default) or `auto`, which behave the same. Any other value returns **500**.\n- The response only confirms that the resend request was sent. It never contains the message, does not guarantee recovery, and no cache lookup is performed.\n- Received view-once media cannot be recovered this way: WhatsApp does not deliver it to linked devices.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRetryMessageRequest"},"examples":{"group_message":{"summary":"Recover a group message","description":"The author of the group message is sent in `SenderJID`.","value":{"MessageID":"3EB0C767D26A1D6B8A9F","ChatJID":"120363000000000011@g.us","SenderJID":"5511888888888@s.whatsapp.net"}},"direct_forced":{"summary":"Recover a direct message without sender","description":"`ForceRetry` sends the request even though `SenderJID` is omitted.","value":{"MessageID":"3EB0C767D26A1D6B8A9F","ChatJID":"5511999999999","ForceRetry":true}},"camel_case_keys":{"summary":"Same request with camelCase keys","description":"Keys are matched case-insensitively.","value":{"messageId":"3EB0C767D26A1D6B8A9F","chatJid":"120363000000000011@g.us","senderJid":"5511888888888@s.whatsapp.net","retryType":"incoming"}}}}}},"responses":{"200":{"description":"Resend request sent to the primary phone; the content arrives later as a `Message` event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatRetryMessageResponse"},"example":{"code":200,"data":{"Details":"Message retry operation completed","Found":true,"Sources":["retry_request"],"RetryAttempts":1,"RetryType":"incoming","CacheStatus":"retry_initiated","ProcessedAt":"2026-09-15T10:30:00-03:00","MessageData":{"retryMethod":"unavailable_message_request","requestedAt":"2026-09-15T10:30:00-03:00","targetChat":"120363000000000011@g.us","targetSender":"5511888888888@s.whatsapp.net"}},"success":true}}}},"400":{"description":"Bad Request: the body is not valid JSON, `MessageID` or `ChatJID` is missing, or a JID cannot be parsed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"missing_message_id":{"summary":"MessageID missing","value":{"code":400,"error":"missing messageId in Payload","success":false}},"missing_chat_jid":{"summary":"ChatJID missing","value":{"code":400,"error":"missing chatJid in Payload","success":false}},"invalid_chat_jid":{"summary":"ChatJID cannot be parsed","value":{"code":400,"error":"invalid chatJid format","success":false}},"invalid_sender_jid":{"summary":"SenderJID cannot be parsed","value":{"code":400,"error":"invalid senderJid format","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, `SenderJID` missing without `ForceRetry`, unsupported `RetryType`, or the resend request could not be sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"sender_required":{"summary":"SenderJID missing and ForceRetry false","value":{"code":500,"error":"senderJid is required for incoming message retry","success":false}},"unsupported_retry_type":{"summary":"RetryType is not incoming or auto","value":{"code":500,"error":"unsupported retry type for this operation","success":false}},"send_failed":{"summary":"Resend request could not be sent","value":{"code":500,"error":"failed to send retry request: websocket not connected","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/newsletter/{newsletterID}":{"delete":{"tags":["Newsletter"],"summary":"Permanently delete an owned channel","description":"Permanently deletes a channel owned by this account. The deletion cannot be undone: the channel, its posts and\nits followers are removed on WhatsApp.\n\n**Rules:**\n- `newsletterID` is the full channel JID (`<digits>@newsletter`, numeric user part, no device), not only the digits.\n- The WhatsApp client must be connected (**500** `client not connected` otherwise).\n- Ownership is enforced by WhatsApp, not by the gateway: deleting a channel this account does not own, or a failed deletion, returns **502** `newsletter deletion was not confirmed`.\n- Do not retry automatically after a 502: check `GET /newsletter/subscribed` first.\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"newsletterID","in":"path","required":true,"description":"Full JID of the channel to delete (`<digits>@newsletter`, no device).","schema":{"type":"string"},"example":"120363000000000022@newsletter"}],"responses":{"200":{"description":"WhatsApp confirmed the deletion.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterDeleteResponse"},"example":{"code":200,"data":{"success":true,"newsletter_jid":"120363000000000022@newsletter"},"success":true}}}},"400":{"description":"Bad Request: the path value is not a non-device `@newsletter` JID with a numeric user part.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"not_newsletter_jid":{"summary":"Not an @newsletter JID","value":{"code":400,"error":"JID must be a non-device @newsletter identifier","success":false}},"non_numeric_user":{"summary":"User part is not numeric","value":{"code":400,"error":"JID user must be numeric","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the client is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"Bad Gateway: WhatsApp did not confirm the deletion (for example, the account is not the channel owner).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"newsletter deletion was not confirmed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/contact-link/resolve":{"post":{"tags":["User"],"summary":"Resolve a WhatsApp contact QR link","description":"Resolves a WhatsApp contact QR link (the \"share my contact\" QR code) to the account it points to. The gateway never downloads the URL: it only extracts the code and asks WhatsApp who owns it.\n\n**Rules:**\n- The body must be a single JSON object of at most 4096 bytes. Unknown fields or a second JSON value are rejected with **400**.\n- `code` is required: 1-2048 bytes, no whitespace or control characters. Send either the bare code or a full URL starting with `https://wa.me/qr/` or `https://api.whatsapp.com/qr/`.\n- Any other URL returns `unsupported contact QR URL`; a supported URL with a query string, fragment or empty code returns `invalid contact QR URL`.\n- The WhatsApp client must exist and be connected (**500** otherwise).\n- A revoked or unknown code returns **404**; any other WhatsApp failure returns **502**.\n\n**Response:**\n- The result is nested twice: `data.success` and `data.data` (`JID`, `Type`, `PushName`), inside the gateway envelope.\n\n**Use Cases:**\n- Turn a scanned contact QR code into a JID before sending the first message\n- Validate QR links collected in a CRM form\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"description":"Contact QR code or supported WhatsApp QR URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.UserContactLinkResolveRequest"},"examples":{"wa_me_url":{"summary":"Full wa.me QR URL","description":"The URL encoded in the QR code shown by \"Share my contact\" in the WhatsApp app.","value":{"code":"https://wa.me/qr/ABCDEFGHIJKL12"}},"api_url":{"summary":"api.whatsapp.com QR URL","description":"The alternative host is accepted too; the gateway only extracts the code after `/qr/`.","value":{"code":"https://api.whatsapp.com/qr/ABCDEFGHIJKL12"}},"bare_code":{"summary":"Bare code","description":"Only the code part of the QR link, without any URL prefix.","value":{"code":"ABCDEFGHIJKL12"}}}}}},"responses":{"200":{"description":"Account behind the contact QR link.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserContactLinkResolveResponse"},"example":{"code":200,"data":{"success":true,"data":{"JID":"5511999999999@s.whatsapp.net","Type":"contact","PushName":"Example Store"}},"success":true}}}},"400":{"description":"Bad Request: the body is not one JSON object within 4096 bytes, or `code` is empty, contains whitespace or uses an unsupported/invalid URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not a JSON object, has unknown fields or exceeds 4096 bytes","value":{"code":400,"error":"invalid JSON object (maximum 4096 bytes)","success":false}},"trailing_data":{"summary":"More than one JSON value in the body","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"bad_code":{"summary":"code missing, empty or containing whitespace","value":{"code":400,"error":"code must contain 1-2048 bytes without whitespace","success":false}},"unsupported_url":{"summary":"URL from another host","value":{"code":400,"error":"unsupported contact QR URL","success":false}},"invalid_url":{"summary":"Supported URL with query string, fragment or no code","value":{"code":400,"error":"invalid contact QR URL","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"Not Found: WhatsApp does not know this code (revoked or never issued).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":404,"error":"contact link not found","success":false}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the client is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Session exists but is not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"Bad Gateway: WhatsApp failed to resolve the code, or returned no result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"contact link resolution failed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/identity-code/{jid}":{"get":{"tags":["User"],"summary":"Get identity verification codes for a LID","description":"Generates the public identity verification (\"security code\") values between this account and a contact: the same 60-digit number and QR payloads shown in the WhatsApp \"Verify security code\" screen.\n\n**Rules:**\n- `jid` must be a non-device `@lid` JID whose user part is numeric; phone JIDs, device JIDs and group JIDs return **400**.\n- The WhatsApp client must exist and be connected (**500** otherwise).\n- The contact's identity keys are fetched from WhatsApp; a failure or an empty answer returns **502**.\n\n**Response:**\n- The result is nested twice: `data.success` and `data.data`, inside the gateway envelope.\n- `DisplayQRCode` and `VerificationQRCode` are byte arrays encoded as base64 strings.\n- `PhoneNumber` and `Username` are empty when unknown. No private identity keys are returned.\n\n**Use Cases:**\n- Show the security code to an operator who verifies a contact in person\n- Detect identity changes by comparing codes over time\n","security":[{"ApiKeyAuth":[]}],"parameters":[{"name":"jid","in":"path","required":true,"description":"Contact LID without device suffix, URL-encoded if your client requires it (`@` may be sent as `%40`).","schema":{"type":"string"},"example":"123456789012345@lid"}],"responses":{"200":{"description":"Identity verification codes for the contact.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserIdentityCodesResponse"},"example":{"code":200,"data":{"success":true,"data":{"UserID":"123456789012345@lid","PhoneNumber":"5511999999999@s.whatsapp.net","Username":"","NumericCode":"123456789012345678901234567890123456789012345678901234567890","DisplayQRCode":"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJw==","VerificationQRCode":"KCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OTw=="}},"success":true}}}},"400":{"description":"Bad Request: `jid` is not a non-device `@lid` JID with a numeric user part.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"not_lid":{"summary":"Phone JID, device JID or other server","value":{"code":400,"error":"JID must be a non-device @lid identifier","success":false}},"non_numeric":{"summary":"LID with a non-numeric user part","value":{"code":400,"error":"JID user must be numeric","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the client is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Session exists but is not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"Bad Gateway: WhatsApp did not return the contact's identity keys.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unavailable":{"summary":"Identity key query failed","value":{"code":502,"error":"identity verification codes unavailable","success":false}},"empty":{"summary":"Query succeeded without codes","value":{"code":502,"error":"identity verification returned no codes","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/user/username/resolve":{"post":{"tags":["User"],"summary":"Resolve a WhatsApp username","description":"Resolves a public WhatsApp username (for example `@examplestore`) to the owner's LID, so you can message an account known only by its username.\n\n**Rules:**\n- The body must be a single JSON object of at most 4096 bytes. Unknown fields or a second JSON value are rejected with **400**.\n- `username` is required: 3-35 characters after trimming surrounding spaces and one leading `@`, with no whitespace or control characters inside.\n- `key` is optional and must be exactly four digits. Send it only when the owner protects the username with a key.\n- The WhatsApp client must exist and be connected (**500** otherwise). A failed WhatsApp query returns **502**.\n\n**Behavior:**\n- When the username needs a key and none (or a wrong one) was sent, the call still returns **200** with `KeyRequired: true` and empty `LID`/`Username`.\n- On success the username is saved in the local contact store for that LID.\n- The result is nested twice: `data.success` and `data.data`, inside the gateway envelope.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"description":"Username to resolve and, when needed, its four-digit key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.UserUsernameResolveRequest"},"examples":{"plain":{"summary":"Username without key","description":"Most usernames resolve without a key.","value":{"username":"examplestore"}},"with_key":{"summary":"Username protected by a key","description":"A leading `@` is accepted; `key` is the four-digit code the owner shared.","value":{"username":"@examplestore","key":"4821"}}}}}},"responses":{"200":{"description":"Resolution result. Check `data.data.KeyRequired` before using `LID`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUsernameResolveResponse"},"examples":{"resolved":{"summary":"Username resolved","value":{"code":200,"data":{"success":true,"data":{"LID":"123456789012345@lid","Username":"examplestore","KeyRequired":false}},"success":true}},"key_required":{"summary":"Key missing or wrong","value":{"code":200,"data":{"success":true,"data":{"LID":"","Username":"","KeyRequired":true}},"success":true}}}}}},"400":{"description":"Bad Request: the body is not one JSON object within 4096 bytes, or `username`/`key` fail validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_json":{"summary":"Body is not a JSON object, has unknown fields or exceeds 4096 bytes","value":{"code":400,"error":"invalid JSON object (maximum 4096 bytes)","success":false}},"trailing_data":{"summary":"More than one JSON value in the body","value":{"code":400,"error":"exactly one JSON object is required","success":false}},"length":{"summary":"username missing, shorter than 3 or longer than 35 characters","value":{"code":400,"error":"username must contain 3-35 characters","success":false}},"whitespace":{"summary":"username with inner whitespace","value":{"code":400,"error":"username contains whitespace or control characters","success":false}},"key":{"summary":"key is not four digits","value":{"code":400,"error":"key must contain four digits","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session for this user, or the client is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Session exists but is not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"Bad Gateway: the WhatsApp username query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"example":{"code":502,"error":"username resolution failed","success":false}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/historysharemode":{"post":{"tags":["Group"],"summary":"Set who can share recent group history","description":"Changes who may share recent message history with new group members: admins only (`admin_share`) or every member\n(`all_member_share`). The gateway writes the `member_share_group_history_mode` group property.\n\n**Rules:**\n- Changes the permission only. It does **not** send old messages and does not add participants; use `POST /group/history/send` to share retained history.\n- The body must be exactly one JSON object; trailing JSON returns **400**.\n- `mode` is validated before `groupjid`. `groupjid` must be a group JID (`@g.us`) without a device part.\n- WhatsApp decides whether this session may change the setting; any library or server failure returns the generic **500** `failed to set group history share mode`.\n- The write goes through WhatsApp's group-property update, the same path the official client uses, and answers in well\n  under a second (measured live: 0.47 s for both modes). The older group IQ for this property is silently ignored by the\n  server, which is why this route used to hang for the full IQ timeout before failing; reading the setting is unchanged.\n- A group that WhatsApp reports in a non-active state fails with the generic **500** instead of reporting success.\n\n**Use Cases:**\n- Allow any member to bring newcomers up to date in a project group\n- Restrict history sharing to admins in groups with sensitive content\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"description":"Group JID and history sharing mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.GroupHistoryShareModeRequest"},"examples":{"admins_only":{"summary":"Only admins can share history","description":"Restricts recent-history sharing to group admins.","value":{"groupjid":"120363000000000011@g.us","mode":"admin_share"}},"all_members":{"summary":"All members can share history","description":"Lets every participant share recent history with new members.","value":{"groupjid":"120363000000000011@g.us","mode":"all_member_share"}}}}}},"responses":{"200":{"description":"WhatsApp accepted the new history share mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailsResponse"},"example":{"code":200,"data":{"Details":"Group history share mode set successfully"},"success":true}}}},"400":{"description":"Bad Request: invalid JSON, more than one JSON value, unaccepted `mode`, or `groupjid` that is not a group JID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"could_not_decode_payload":{"summary":"Body is not valid JSON","value":{"code":400,"error":"could not decode Payload","success":false}},"expected_single_payload":{"summary":"Trailing JSON after the object","value":{"code":400,"error":"expected a single JSON payload","success":false}},"invalid_mode":{"summary":"mode is missing or not accepted","value":{"code":400,"error":"invalid mode, must be 'admin_share' or 'all_member_share'","success":false}},"not_a_group_jid":{"summary":"groupjid is not an @g.us JID","value":{"code":400,"error":"groupjid must be a group JID","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, or the library/WhatsApp rejected the change.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"change_failed":{"summary":"Change rejected","value":{"code":500,"error":"failed to set group history share mode","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/catalog/own":{"get":{"tags":["Business"],"summary":"Get the own catalog, including hidden products","description":"Reads the administrative catalog of the paired business account through the authenticated Meta management query, including hidden products and products still under review.\n\n**Features:**\n- Catalog ID, type and name plus one page of products with review status (`status_info`) and visibility (`is_hidden`)\n- Pagination with `limit` and `cursor`; pass `next` as the next `cursor`\n\n**Rules:**\n- `limit` 1-100 (default 20) and `cursor` (at most 2048 bytes) are validated before the session check (`400`)\n- Prices are strings with integer thousandths of the currency (`\"3000000\"` = 3,000.00)\n- Does not create or modify products, does not retry and does not use the catalog cache\n- Token exchange or query failures return `502 own business catalog unavailable: <reason>`; token acquisition may require the primary phone to be online\n\n**Use Cases:**\n- Read a product completely before `PUT /business/products/{productID}`\n- Track products pending Meta review\n","parameters":[{"name":"limit","in":"query","required":false,"description":"Page size, 1-100 (default 20). Must appear at most once.","schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"example":20},{"name":"cursor","in":"query","required":false,"description":"Opaque cursor copied from `next` of the previous page. At most once and 2048 bytes.","schema":{"type":"string","maxLength":2048},"example":"AQHRcursorEXAMPLE"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Own catalog page","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Typed business result wrapper.","required":["success","data"],"properties":{"success":{"type":"boolean","description":"Always true when the operation succeeded.","example":true},"data":{"type":"object","description":"Own catalog page.","properties":{"catalog_id":{"type":"string","description":"Catalog ID.","example":"7123456789012300"},"catalog_type":{"type":"string","description":"Catalog type reported by Meta.","example":"NATIVE"},"catalog_name":{"type":"string","description":"Catalog name.","example":"Example Store"},"products":{"type":"array","description":"Products on this page, including hidden and pending ones.","items":{"$ref":"#/components/schemas/BusinessCatalogProduct"}},"next":{"type":"string","description":"Cursor for the next page; omitted on the last page.","example":"AQHRcursorEXAMPLE"},"previous":{"type":"string","description":"Cursor for the previous page, when present.","example":"AQHRcursorPREVIOUS"}}}}}}}]},"examples":{"first_page":{"summary":"First page with one product","value":{"code":200,"data":{"data":{"catalog_id":"7123456789012300","catalog_type":"NATIVE","catalog_name":"Example Store","products":[{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"APPROVED"}}],"next":"AQHRcursorEXAMPLE"},"success":true},"success":true}}}}}},"400":{"description":"Invalid pagination: `limit must be between 1 and 100`; `limit must be provided once`; `cursor must be provided once and contain at most 2048 bytes`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"limit_out_of_range":{"summary":"limit out of range","value":{"code":400,"error":"limit must be between 1 and 100","success":false}},"repeated_limit":{"summary":"Repeated limit","value":{"code":400,"error":"limit must be provided once","success":false}},"repeated_or_oversized_cursor":{"summary":"Repeated or oversized cursor","value":{"code":400,"error":"cursor must be provided once and contain at most 2048 bytes","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The user has no WhatsApp session or it is not connected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}}}}}},"502":{"description":"The Meta token exchange or catalog query failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"primary_phone_offline":{"summary":"Primary phone offline","value":{"code":502,"error":"own business catalog unavailable: business access token recovery is required on the primary device","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/accept":{"post":{"tags":["Business"],"summary":"Accept a received order with a linked billing","description":"Accepts an order received from a buyer by sending a billing message that quotes the original `OrderMessage`. No order enum is mutated.\n\n**Features:**\n- `billing.order_request_id` is derived from the verified incoming order\n- The header thumbnail is the order's own JPEG thumbnail (≤ 1 MiB); custom images are not allowed\n- The acknowledged billing is stored for later declarations (`X-Billing-Metadata-Status`)\n\n**Rules:**\n- `to`, `incoming_message_id` and `billing` are required; `body` and `id` are optional\n- `incoming_message_id` must be an `OrderMessage` received from this buyer and stored by this instance (`409 verified original message unavailable for this user, buyer and reference`)\n- One decision per received order: after an accept or reject sent by this instance (or taken on the seller's phone and observed by the gateway), a second accept/reject for the same `incoming_message_id` returns `409 order already <accepted|rejected> by message <id>; nothing sent`\n- Order state: the gateway records the decision in its own order state (`GET /business/order/state/{messageID}`), emits the `OrderState` webhook event and adds `order_state` to the response\n- Seller devices: the official WhatsApp apps keep the order/billing card state (Accept/Decline buttons, \"Update status\" screen) only on the device that acted. No message or mutation updates the seller's other devices, so after a decision sent by the API the seller's phone keeps showing its local state; the buyer receives every message normally. Responses carry `seller_card_state: \"local_to_acting_device\"` (validated live 2026-09-22, including the official iPhone app, whose wire matches this route)\n- Recommended lifecycle: accept (`/business/order/accept`), then `/business/order/payment/status/send` with `status: captured` (the official app sends it without `order`), then `/business/order/status/send` with `completed`; each quotes the billing created by the accept\n- Forbidden (`400`): `image`, `billing.order_request_id`, `billing_message_id`, `reference_id`, `status`, `order_status`, `payment_method`, `payment_timestamp`\n- `400 failed to attach verified original quote` when the quote cannot be built\n\n**Billing rules** (library validation, `400` with the builder error):\n- `reference_id` 1-256 bytes; `type` `physical-goods`; `currency` three uppercase letters; `order.order_type` `ORDER`; `order.status` `payment_requested`\n- 1-100 `order.items`, each with `name` (≤ 256), `quantity` 1-100, `product_id` or `retailer_id` and `amount`; custom items need `isCustomItem: true` and `retailer_id` starting with `custom-item` without `product_id`\n- Amounts are `{value, offset}` (`value/offset`); `order.subtotal` = Σ quantity × amount; `total_amount` = subtotal − discount + shipping + tax (discount ≤ subtotal)\n- At least one payment configuration: `payment_settings` (≤ 2, no repeated type) and/or `external_payment_configurations` (≤ 5)\n","requestBody":{"required":true,"description":"Buyer, received order message ID and explicit billing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessBillingSendRequest"},"examples":{"accept":{"summary":"Accept a received order","description":"Quotes the received order and requests payment with PIX.","value":{"to":"5511999999999@s.whatsapp.net","incoming_message_id":"3EB0C767D26A1D6B8A9F","body":"Order accepted. Please review and pay.","billing":{"reference_id":"REF-0003","type":"physical-goods","currency":"BRL","total_amount":{"value":15000,"offset":100},"order":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"subtotal":{"value":15000,"offset":100}},"payment_settings":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}}]}}},"every_payment_method":{"summary":"Accept offering PIX, card and external instructions","description":"The three payment surfaces the protocol allows, in one billing: PIX static code, the native card option and free-text instructions (where a boleto, a checkout link or bank details go). At most two payment_settings, one per type; up to five external_payment_configurations. None of them moves money - the buyer pays outside the API and the seller declares the result with POST /business/order/payment/status/send.","value":{"to":"5511999999999@s.whatsapp.net","incoming_message_id":"3EB0C767D26A1D6B8A9F","body":"Order accepted. Pay with PIX, card or the link below.","billing":{"reference_id":"REF-0004","type":"physical-goods","currency":"BRL","total_amount":{"value":7500000,"offset":1000},"order":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Automation setup","quantity":1,"amount":{"value":5000000,"offset":1000}},{"product_id":"7123456789012346","name":"WhatsApp API consulting","quantity":1,"amount":{"value":2500000,"offset":1000}}],"subtotal":{"value":7500000,"offset":1000}},"payment_settings":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}},{"type":"cards","cards":{"enabled":true}}],"external_payment_configurations":[{"type":"payment_instruction","payment_instruction":"Boleto or hosted checkout: https://example.com/checkout/REF-0004"}]}}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Message acknowledged","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Billing message acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"effect":{"type":"string","description":"Always `message_sent`: only a message was sent.","example":"message_sent"},"financial_transaction_performed":{"type":"boolean","description":"Always false: no bank or payment transaction is performed.","example":false}}}}}]},"examples":{"sent":{"summary":"Billing message acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","effect":"message_sent","financial_transaction_performed":false},"success":true}}}}},"headers":{"X-Billing-Metadata-Status":{"description":"`stored` or `unavailable`. `unavailable` means later declarations cannot quote this billing; it does NOT mean the send failed, so do not resend.","schema":{"type":"string","enum":["stored","unavailable"]},"example":"stored"}}},"400":{"description":"Invalid request: `accept uses the verified incoming order thumbnail; image override is not allowed`; `failed to attach verified original quote`; `invalid billing request`; `only one JSON object is allowed`; `explicit individual buyer and valid message ID are required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"image_not_allowed":{"summary":"Image not allowed","value":{"code":400,"error":"accept uses the verified incoming order thumbnail; image override is not allowed","success":false}},"quote_cannot_be_attached":{"summary":"Quote cannot be attached","value":{"code":400,"error":"failed to attach verified original quote","success":false}},"malformed_body_or_unknown_field":{"summary":"Malformed body or unknown field","value":{"code":400,"error":"invalid billing request","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"only one JSON object is allowed","success":false}},"invalid_buyer_or_message_id":{"summary":"Invalid buyer or message ID","value":{"code":400,"error":"explicit individual buyer and valid message ID are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"The instance identity or the verified original message is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"own_device_identity_missing":{"summary":"Own device identity missing","value":{"code":409,"error":"own device identity unavailable","success":false}},"incoming_order_not_stored":{"summary":"Incoming order not stored","value":{"code":409,"error":"verified original message unavailable for this user, buyer and reference","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the buyer PN/LID lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"buyer_identity_lookup_failed":{"summary":"Buyer identity lookup failed","value":{"code":500,"error":"buyer identity lookup failed","success":false}}}}}},"502":{"description":"WhatsApp did not acknowledge the message. Delivery is not confirmed; do not retry blindly because the buyer may have received it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"send_not_acknowledged":{"summary":"Send not acknowledged","value":{"code":502,"error":"billing message send failed; delivery is not confirmed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/charge/send":{"post":{"tags":["Business"],"summary":"Send a billing message","description":"Sends a standalone billing (\"review and pay\") message to a buyer: an interactive message with the `review_and_pay` button carrying the `billing` payload.\n\n**Features:**\n- PIX static code, cards and external payment instructions\n- Optional `image` (JPEG/PNG base64 or `data:` URI within the 256 KiB body limit) becomes a 72×72 JPEG header thumbnail\n- The acknowledged billing is stored so later status and payment declarations can quote it (`X-Billing-Metadata-Status`)\n\n**Rules:**\n- `to` and `billing` are required; `body` and `id` are optional\n- Forbidden in this mode (`400 invalid billing creation fields; order_request_id is derived from verified incoming order only`): `billing.order_request_id`, `incoming_message_id`, `billing_message_id`, `reference_id`, `status`, `order_status`, `payment_method`, `payment_timestamp`\n\n**Billing rules** (library validation, `400` with the builder error):\n- `reference_id` 1-256 bytes; `type` `physical-goods`; `currency` three uppercase letters; `order.order_type` `ORDER`; `order.status` `payment_requested`\n- 1-100 `order.items`, each with `name` (≤ 256), `quantity` 1-100, `product_id` or `retailer_id` and `amount`; custom items need `isCustomItem: true` and `retailer_id` starting with `custom-item` without `product_id`\n- Amounts are `{value, offset}` (`value/offset`); `order.subtotal` = Σ quantity × amount; `total_amount` = subtotal − discount + shipping + tax (discount ≤ subtotal)\n- At least one payment configuration: `payment_settings` (≤ 2, no repeated type) and/or `external_payment_configurations` (≤ 5)\n","requestBody":{"required":true,"description":"Buyer, optional text and explicit billing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessBillingSendRequest"},"examples":{"pix":{"summary":"Minimal charge with PIX","description":"One catalog item paid with a PIX static code.","value":{"to":"5511999999999@s.whatsapp.net","body":"Your order is ready for payment.","billing":{"reference_id":"REF-0001","type":"physical-goods","currency":"BRL","total_amount":{"value":15000,"offset":100},"order":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"subtotal":{"value":15000,"offset":100}},"payment_settings":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}}]}}},"full":{"summary":"Custom item, discount, shipping, cards and external link","description":"Two lines (one custom), discount and shipping, card payment and an external payment instruction.","value":{"to":"5511999999999@s.whatsapp.net","id":"3EB0C767D26A1D6B8A90","body":"Your order is ready for payment.","billing":{"reference_id":"REF-0002","type":"physical-goods","currency":"BRL","total_amount":{"value":32000,"offset":100},"order":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":2,"amount":{"value":15000,"offset":100}},{"isCustomItem":true,"retailer_id":"custom-item-assembly","name":"Assembly service","quantity":1,"amount":{"value":3000,"offset":100}}],"subtotal":{"value":33000,"offset":100},"discount":{"value":3000,"offset":100},"shipping":{"value":2000,"offset":100}},"additional_note":"Delivery in 5 business days.","payment_settings":[{"type":"cards","cards":{"enabled":true}}],"external_payment_configurations":[{"type":"payment_instruction","payment_instruction":"Pay at https://example.com/pay/REF-0002"}]}}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Message acknowledged","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Billing message acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"effect":{"type":"string","description":"Always `message_sent`: only a message was sent.","example":"message_sent"},"financial_transaction_performed":{"type":"boolean","description":"Always false: no bank or payment transaction is performed.","example":false}}}}}]},"examples":{"sent":{"summary":"Billing message acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","effect":"message_sent","financial_transaction_performed":false},"success":true}}}}},"headers":{"X-Billing-Metadata-Status":{"description":"`stored` or `unavailable`. `unavailable` means later declarations cannot quote this billing; it does NOT mean the send failed, so do not resend.","schema":{"type":"string","enum":["stored","unavailable"]},"example":"stored"}}},"400":{"description":"Invalid request: `invalid billing creation fields; order_request_id is derived from verified incoming order only`; `billing total does not equal subtotal minus discount plus shipping and tax`; `invalid billing request`; `only one JSON object is allowed`; `explicit individual buyer and valid message ID are required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"forbidden_creation_fields":{"summary":"Forbidden creation fields","value":{"code":400,"error":"invalid billing creation fields; order_request_id is derived from verified incoming order only","success":false}},"totals_do_not_match":{"summary":"Totals do not match","value":{"code":400,"error":"billing total does not equal subtotal minus discount plus shipping and tax","success":false}},"malformed_body_or_unknown_field":{"summary":"Malformed body or unknown field","value":{"code":400,"error":"invalid billing request","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"only one JSON object is allowed","success":false}},"invalid_buyer_or_message_id":{"summary":"Invalid buyer or message ID","value":{"code":400,"error":"explicit individual buyer and valid message ID are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"The instance identity or the verified original message is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"own_device_identity_missing":{"summary":"Own device identity missing","value":{"code":409,"error":"own device identity unavailable","success":false}},"quote_cannot_be_represented":{"summary":"Quote cannot be represented","value":{"code":409,"error":"verified billing quote cannot represent this declaration","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the buyer PN/LID lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"buyer_identity_lookup_failed":{"summary":"Buyer identity lookup failed","value":{"code":500,"error":"buyer identity lookup failed","success":false}}}}}},"502":{"description":"WhatsApp did not acknowledge the message. Delivery is not confirmed; do not retry blindly because the buyer may have received it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"send_not_acknowledged":{"summary":"Send not acknowledged","value":{"code":502,"error":"billing message send failed; delivery is not confirmed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/payment/status/send":{"post":{"tags":["Business"],"summary":"Send a payment status declaration","description":"Sends a payment status declaration (`payment_status` native flow) quoting a billing message previously sent by this instance. It does not move money and does not verify any payment.\n\n**Rules:**\n- Seller devices keep the billing \"Update status\" screen state locally (official app behavior): the buyer sees the declaration, the seller's phone does not change its screen. Responses carry `seller_card_state: \"local_to_acting_device\"`\n- Order state: when the billing belongs to an order tracked by the gateway (accepted by `POST /business/order/accept` or on the phone), the order must be `accepted` — `409 order not accepted; nothing sent`, `409 order rejected; nothing sent`, and after `completed` or `canceled` `409 order already <completed|canceled>; nothing sent` — checked before sending. On success the state is updated (`GET /business/order/state/{messageID}`), the `OrderState` webhook event is emitted and `order_state` is added to the response. Standalone charges are not enforced\n- `to`, `billing_message_id`, `reference_id` and `status` are required; `status` is `pending`, `captured` or `failed`\n- At least one of `payment_method` (≤ 64 bytes) or `payment_timestamp` (positive integer) is required\n- `order_status` is optional and uses the order lifecycle values (`pending`, `processing`, `partially_shipped`, `shipped`, `completed`, `canceled`, `payment_requested`, `preparing_to_ship`, `delivered`, `confirmed`, `delayed`, `out_for_delivery`, `failed`, `refunded`)\n- Invalid combinations return `400 invalid payment lifecycle claim`\n- Forbidden: `image`, `billing`, `incoming_message_id` (`400 own billing_message_id and reference_id are required`)\n- The billing must be stored for this user, buyer and reference and contain one `review_and_pay` button (`409`)\n- Like the order status route, the billing is quoted unchanged. The declaration reaches the buyer as its own message\n  (a \"payment received\" bubble); it does not flip the \"Paid\" toggle on the billing card, which only the seller's app\n  controls.\n","requestBody":{"required":true,"description":"Buyer, own billing message, reference and payment claim.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessBillingSendRequest"},"examples":{"captured":{"summary":"Payment captured","description":"Declares a captured PIX payment and moves the order to processing.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"captured","payment_method":"pix","payment_timestamp":1757937600,"order_status":"processing","body":"Payment received, thank you."}},"method_only":{"summary":"Pending with method only","description":"Declares a pending payment identified only by its method.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"pending","payment_method":"pix"}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Message acknowledged","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Billing message acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"effect":{"type":"string","description":"Always `message_sent`: only a message was sent.","example":"message_sent"},"financial_transaction_performed":{"type":"boolean","description":"Always false: no bank or payment transaction is performed.","example":false}}}}}]},"examples":{"sent":{"summary":"Billing message acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","effect":"message_sent","financial_transaction_performed":false},"success":true}}}}}},"400":{"description":"Invalid request: `invalid payment lifecycle claim`; `own billing_message_id and reference_id are required`; `invalid billing request`; `only one JSON object is allowed`; `explicit individual buyer and valid message ID are required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_payment_claim":{"summary":"Invalid payment claim","value":{"code":400,"error":"invalid payment lifecycle claim","success":false}},"billing_reference_missing":{"summary":"Billing reference missing","value":{"code":400,"error":"own billing_message_id and reference_id are required","success":false}},"malformed_body_or_unknown_field":{"summary":"Malformed body or unknown field","value":{"code":400,"error":"invalid billing request","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"only one JSON object is allowed","success":false}},"invalid_buyer_or_message_id":{"summary":"Invalid buyer or message ID","value":{"code":400,"error":"explicit individual buyer and valid message ID are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"The instance identity or the verified original message is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"own_device_identity_missing":{"summary":"Own device identity missing","value":{"code":409,"error":"own device identity unavailable","success":false}},"billing_not_stored_for_buyer_and_reference":{"summary":"Billing not stored for buyer and reference","value":{"code":409,"error":"verified original message unavailable for this user, buyer and reference","success":false}},"quote_is_not_a_review_and_pay_billing":{"summary":"Quote is not a review_and_pay billing","value":{"code":409,"error":"verified billing quote cannot represent this declaration","success":false}},"order_state_not_accepted":{"summary":"Tracked order not accepted","value":{"code":409,"error":"order not accepted; nothing sent","success":false}},"order_state_rejected":{"summary":"Tracked order rejected","value":{"code":409,"error":"order rejected; nothing sent","success":false}},"order_state_terminal":{"summary":"Tracked order already completed","value":{"code":409,"error":"order already completed; nothing sent","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the buyer PN/LID lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"buyer_identity_lookup_failed":{"summary":"Buyer identity lookup failed","value":{"code":500,"error":"buyer identity lookup failed","success":false}}}}}},"502":{"description":"WhatsApp did not acknowledge the message. Delivery is not confirmed; do not retry blindly because the buyer may have received it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"send_not_acknowledged":{"summary":"Send not acknowledged","value":{"code":502,"error":"billing message send failed; delivery is not confirmed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/status/send":{"post":{"tags":["Business"],"summary":"Send an order status declaration","description":"Sends an order lifecycle declaration (`review_order` native flow) quoting a billing message previously sent by this instance, with the new status written into the quoted order.\n\n**Rules:**\n- Seller devices keep the billing \"Update status\" screen state locally (official app behavior): the buyer sees the declaration, the seller's phone does not change its screen. Responses carry `seller_card_state: \"local_to_acting_device\"`\n- Order state: when the billing belongs to an order tracked by the gateway (accepted by `POST /business/order/accept` or on the phone), the order must be `accepted` — `409 order not accepted; nothing sent`, `409 order rejected; nothing sent`, and after `completed` or `canceled` `409 order already <completed|canceled>; nothing sent` — checked before sending. On success the state is updated (`GET /business/order/state/{messageID}`), the `OrderState` webhook event is emitted and `order_state` is added to the response. Standalone charges are not enforced\n- `to`, `billing_message_id` (own billing message ID), `reference_id` (the `billing.reference_id` of that billing) and `status` are required; `body` and `id` are optional\n- `status` must be one of `pending`, `processing`, `partially_shipped`, `shipped`, `completed`, `canceled`, `payment_requested`, `preparing_to_ship`, `delivered`, `confirmed`, `delayed`, `out_for_delivery`, `failed`, `refunded` (`400 invalid order lifecycle claim`)\n- Forbidden: `image`, `billing`, `incoming_message_id` (`400 own billing_message_id and reference_id are required`) and `payment_method`, `payment_timestamp`, `order_status` (`400 payment fields are not order status fields`)\n- The billing must be stored for this user, buyer and reference and contain one `review_and_pay` button (`409`)\n- The declaration quotes the billing **exactly as it was sent**: the quoted payload is never rewritten, matching what the\n  official client does.\n- **The order card does not follow these declarations.** Each one arrives as its own message (\"Status: shipped\", and so\n  on), which is what the buyer reads; the badge on the billing card only moves through the seller's own app. The client\n  reserves card updates for a button name (`order_status`) that the buyer's app does not render — measured live on\n  2026-09-16, both ways. Treat the messages as the delivery channel, not the card.\n\n**Typical sequence** (validated end to end on a real order): `POST /business/order/accept` sends the billing, then this\nroute walks the order through `confirmed` -> `processing` -> `preparing_to_ship` -> `shipped` -> `out_for_delivery` ->\n`delivered` -> `completed`. Each call is an independent declaration quoting the same billing: any order of non-terminal statuses is\naccepted and the buyer sees every declaration; for an order tracked by the gateway, declarations stop after `completed` or\n`canceled` (`409`). Payment is declared\nseparately with `POST /business/order/payment/status/send`.\n","requestBody":{"required":true,"description":"Buyer, own billing message, reference and status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessBillingSendRequest"},"examples":{"shipped":{"summary":"Order shipped","description":"Declares that the order quoted by the billing was shipped.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"shipped","body":"Your order is on its way."}},"confirmed":{"summary":"Order confirmed (first step after accepting)","description":"Opens the lifecycle right after the billing was sent.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"confirmed","body":"Order confirmed. We are preparing it now."}},"delivered":{"summary":"Order delivered","description":"Declared when the buyer has the goods; `completed` usually follows.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"delivered"}},"completed":{"summary":"Order completed (closes the lifecycle)","description":"Last declaration of the flow; nothing prevents sending further statuses afterwards.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"completed"}},"canceled":{"summary":"Order canceled","description":"Declares the order as canceled without extra text.","value":{"to":"5511999999999@s.whatsapp.net","billing_message_id":"3EB0C767D26A1D6B8A9F","reference_id":"REF-0001","status":"canceled"}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Message acknowledged","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Billing message acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"effect":{"type":"string","description":"Always `message_sent`: only a message was sent.","example":"message_sent"},"financial_transaction_performed":{"type":"boolean","description":"Always false: no bank or payment transaction is performed.","example":false}}}}}]},"examples":{"sent":{"summary":"Billing message acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","effect":"message_sent","financial_transaction_performed":false},"success":true}}}}}},"400":{"description":"Invalid request: `invalid order lifecycle claim`; `own billing_message_id and reference_id are required`; `payment fields are not order status fields`; `invalid billing request`; `only one JSON object is allowed`; `explicit individual buyer and valid message ID are required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"unknown_status":{"summary":"Unknown status","value":{"code":400,"error":"invalid order lifecycle claim","success":false}},"billing_reference_missing":{"summary":"Billing reference missing","value":{"code":400,"error":"own billing_message_id and reference_id are required","success":false}},"payment_fields_sent":{"summary":"Payment fields sent","value":{"code":400,"error":"payment fields are not order status fields","success":false}},"malformed_body_or_unknown_field":{"summary":"Malformed body or unknown field","value":{"code":400,"error":"invalid billing request","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"only one JSON object is allowed","success":false}},"invalid_buyer_or_message_id":{"summary":"Invalid buyer or message ID","value":{"code":400,"error":"explicit individual buyer and valid message ID are required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"The instance identity or the verified original message is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"own_device_identity_missing":{"summary":"Own device identity missing","value":{"code":409,"error":"own device identity unavailable","success":false}},"billing_not_stored_for_buyer_and_reference":{"summary":"Billing not stored for buyer and reference","value":{"code":409,"error":"verified original message unavailable for this user, buyer and reference","success":false}},"quote_is_not_a_review_and_pay_billing":{"summary":"Quote is not a review_and_pay billing","value":{"code":409,"error":"verified billing quote cannot represent this declaration","success":false}},"order_state_not_accepted":{"summary":"Tracked order not accepted","value":{"code":409,"error":"order not accepted; nothing sent","success":false}},"order_state_rejected":{"summary":"Tracked order rejected","value":{"code":409,"error":"order rejected; nothing sent","success":false}},"order_state_terminal":{"summary":"Tracked order already completed","value":{"code":409,"error":"order already completed; nothing sent","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the buyer PN/LID lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"buyer_identity_lookup_failed":{"summary":"Buyer identity lookup failed","value":{"code":500,"error":"buyer identity lookup failed","success":false}}}}}},"502":{"description":"WhatsApp did not acknowledge the message. Delivery is not confirmed; do not retry blindly because the buyer may have received it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"send_not_acknowledged":{"summary":"Send not acknowledged","value":{"code":502,"error":"billing message send failed; delivery is not confirmed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/reject":{"post":{"tags":["Business"],"summary":"Send an order refusal message","description":"Refuses a received order by replying to the original `OrderMessage` with WhatsApp's official refusal text plus an optional note.\n\n**Features:**\n- The sent text is the fixed Portuguese sentence `Este pedido foi recusado.` (as written by the official app), followed by a line break and `body` when present\n- Quotes the verified incoming order\n\n**Rules:**\n- Body: exactly one JSON object, unknown fields rejected, maximum 16 KiB (`400 invalid order rejection request` / `only one JSON object is allowed`)\n- `to` must be an individual buyer JID (`@s.whatsapp.net` or `@lid`, no device); `incoming_message_id` 1-128 bytes; `id` ≤ 128 bytes; `body` ≤ 4096 bytes\n- The incoming order must be stored for this user and buyer (`409 verified incoming order unavailable for this user and buyer`)\n- Does not mutate an order enum and does not verify the remote order state (`remote_order_state_verified: false`)\n- One decision per received order: after an accept or reject sent by this instance (or taken on the seller's phone and observed by the gateway), a second accept/reject for the same `incoming_message_id` returns `409 order already <accepted|rejected> by message <id>; nothing sent`\n- Order state: the gateway records the decision in its own order state (`GET /business/order/state/{messageID}`), emits the `OrderState` webhook event and adds `order_state` to the response\n- Seller devices: the official WhatsApp apps keep the order/billing card state (Accept/Decline buttons, \"Update status\" screen) only on the device that acted. No message or mutation updates the seller's other devices, so after a decision sent by the API the seller's phone keeps showing its local state; the buyer receives every message normally. Responses carry `seller_card_state: \"local_to_acting_device\"` (validated live 2026-09-22, including the official iPhone app, whose wire matches this route)\n","requestBody":{"required":true,"description":"Buyer, received order message ID and optional note.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.BusinessOrderRejectRequest"},"examples":{"minimal":{"summary":"Refuse without note","description":"Sends only the official refusal sentence.","value":{"to":"5511999999999@s.whatsapp.net","incoming_message_id":"3EB0C767D26A1D6B8A9F"}},"with_note":{"summary":"Refuse with note and custom message ID","description":"Adds a note on the next line and sets the outgoing message ID.","value":{"to":"5511999999999@s.whatsapp.net","incoming_message_id":"3EB0C767D26A1D6B8A9F","id":"3EB0C767D26A1D6B8A90","body":"Item out of stock."}}}}}},"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Refusal message acknowledged","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Refusal acknowledgement.","properties":{"success":{"type":"boolean","description":"Always true when WhatsApp acknowledged the message.","example":true},"message_id":{"type":"string","description":"WhatsApp message ID of the sent message.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time (RFC 3339).","format":"date-time","example":"2026-09-15T12:00:00Z"},"to":{"type":"string","description":"Recipient JID the message was sent to.","example":"5511999999999@s.whatsapp.net"},"effect":{"type":"string","description":"Always `rejection_message_sent`.","example":"rejection_message_sent"},"remote_order_state_verified":{"type":"boolean","description":"Always false: the remote order state is not checked.","example":false}}}}}]},"examples":{"sent":{"summary":"Refusal acknowledged","value":{"code":200,"data":{"success":true,"message_id":"3EB0C767D26A1D6B8A9F","timestamp":"2026-09-15T12:00:00Z","to":"5511999999999@s.whatsapp.net","effect":"rejection_message_sent","remote_order_state_verified":false},"success":true}}}}}},"400":{"description":"Invalid request: `invalid order rejection request`; `only one JSON object is allowed`; `individual buyer, incoming_message_id and bounded rejection note are required`; `failed to attach verified original quote`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"malformed_body_or_unknown_field":{"summary":"Malformed body or unknown field","value":{"code":400,"error":"invalid order rejection request","success":false}},"more_than_one_json_value":{"summary":"More than one JSON value","value":{"code":400,"error":"only one JSON object is allowed","success":false}},"invalid_buyer_message_id_or_note":{"summary":"Invalid buyer, message ID or note","value":{"code":400,"error":"individual buyer, incoming_message_id and bounded rejection note are required","success":false}},"quote_cannot_be_attached":{"summary":"Quote cannot be attached","value":{"code":400,"error":"failed to attach verified original quote","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"The instance identity or the verified incoming order is not available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"own_device_identity_missing":{"summary":"Own device identity missing","value":{"code":409,"error":"own device identity unavailable","success":false}},"incoming_order_not_stored":{"summary":"Incoming order not stored","value":{"code":409,"error":"verified incoming order unavailable for this user and buyer","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"No session, client not connected, or the buyer PN/LID lookup failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No session","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"Client not connected","value":{"code":500,"error":"client not connected","success":false}},"buyer_identity_lookup_failed":{"summary":"Buyer identity lookup failed","value":{"code":500,"error":"buyer identity lookup failed","success":false}}}}}},"502":{"description":"WhatsApp did not acknowledge the message. Delivery is not confirmed; do not retry blindly.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"send_not_acknowledged":{"summary":"Send not acknowledged","value":{"code":502,"error":"rejection message send failed; delivery is not confirmed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/group/history/send":{"post":{"tags":["Group"],"summary":"Send retained group history to selected members","description":"Shares group messages that this gateway retained for the user with selected current members, as a recent-history\nbundle. The sequence mirrors the official linked client: upload the history blob, send a `MessageHistoryBundle`\nmessage (`bundle_id`), then a `MessageHistoryNotice` message (`notice_id`). It never adds members and never retries.\n\n**Rules:**\n- Body: one JSON object, at most 32 KiB, unknown fields rejected. All five fields are required.\n- `group_jid`: `@g.us` JID without device. `message_ids`: 1-100 distinct IDs (max 128 chars) of group messages retained for this user and group.\n- `recipients`: 1-100 distinct phone numbers or user JIDs (`@s.whatsapp.net` / `@lid`, no device). Each must be another current member; the session itself is not a valid recipient.\n- `bundle_id` and `notice_id`: non-empty, max 128 chars, different from each other, never used before.\n- Only primary content is retained (text, media, contacts, locations, polls, events, stickers, invites); reactions, votes, edits and view-once content are not.\n- Retention is bounded: originals are kept for `GLOBAL_GROUP_HISTORY_RETENTION_DAYS` (default 90, which is also the maximum; `0` disables retention) and at most `GLOBAL_GROUP_HISTORY_RETENTION_MAX_PER_USER` (default 100000) newest originals per user. A message outside the window answers the same **409** as a message that was never retained; retained messages behave exactly as before.\n\n**Side Effects:**\n- Both IDs are durably reserved **before** any network call. Reusing either returns **409**, even when the earlier attempt failed.\n- Admin membership and recipient membership are checked by the library after the reservation, so a failure there also consumes the IDs (**502**, `phase: validation`).\n\n**Delivery:**\n- `bundle_acknowledged` / `notice_acknowledged` are server acknowledgements only. `recipient_delivery_verified` is always `false` and `retry_safe` is always `false`.\n- **502** keeps the legacy envelope: top-level `success` is `true`; inspect `data.success`, `data.result.phase` and `data.error`.\n","security":[{"ApiKeyAuth":[]}],"requestBody":{"required":true,"description":"Group, retained message IDs, recipients and two unused operation IDs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.GroupHistorySendRequest"},"examples":{"one_recipient":{"summary":"Share two retained messages with one member","description":"Recipient given as a phone number; both operation IDs are new.","value":{"group_jid":"120363000000000011@g.us","message_ids":["3EB0C767D26A1D6B8A9F","3EB0C767D26A1D6B8A9E"],"recipients":["5511988888888"],"bundle_id":"3EB0C767D26A1D6B8AA0","notice_id":"3EB0C767D26A1D6B8AA1"}},"jid_recipients":{"summary":"Recipients as user JIDs","description":"Phone JID and LID recipients may be mixed; each must resolve to a different current member.","value":{"group_jid":"120363000000000011@g.us","message_ids":["3EB0C767D26A1D6B8A9F"],"recipients":["5511988888888@s.whatsapp.net","123456789012345@lid"],"bundle_id":"3EB0C767D26A1D6B8AB0","notice_id":"3EB0C767D26A1D6B8AB1"}}}}}},"responses":{"200":{"description":"Bundle and notice were both acknowledged by the WhatsApp server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupHistorySendResponse"},"example":{"code":200,"data":{"success":true,"result":{"bundle_id":"3EB0C767D26A1D6B8AA0","notice_id":"3EB0C767D26A1D6B8AA1","phase":"acknowledged","bundle_acknowledged":true,"notice_acknowledged":true},"retry_safe":false,"recipient_delivery_verified":false,"evidence_persisted":true},"success":true}}}},"400":{"description":"Bad Request: invalid or oversized JSON, unknown fields, trailing JSON, invalid group/IDs, invalid or duplicate recipient or message ID, or a history window over 16 MiB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"invalid_history_request":{"summary":"Invalid JSON, unknown field or body over 32 KiB","value":{"code":400,"error":"invalid history request","success":false}},"only_one_json_object":{"summary":"Trailing JSON after the object","value":{"code":400,"error":"only one JSON object allowed","success":false}},"invalid_group_or_ids":{"summary":"Missing or invalid group, list sizes or operation IDs","value":{"code":400,"error":"invalid group, messages, recipients or operation IDs","success":false}},"invalid_recipient":{"summary":"Recipient is not a user JID or is repeated","value":{"code":400,"error":"invalid or duplicate history recipient","success":false}},"invalid_message_id":{"summary":"Message ID empty, too long or repeated","value":{"code":400,"error":"invalid or duplicate original message ID","success":false}},"window_too_large":{"summary":"Retained history exceeds the size limit","value":{"code":400,"error":"history window exceeds limits","success":false}}}}}},"401":{"description":"Missing or invalid user token (header `token` or query `token`).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"gateway":{"summary":"Resposta já documentada da operação","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"409":{"description":"Conflict: a requested message is not retained for this user and group, or `bundle_id`/`notice_id` was already reserved. Nothing was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"original_unavailable":{"summary":"Message not retained","value":{"code":409,"error":"original history unavailable for this user and group","success":false}},"ids_already_used":{"summary":"bundle_id or notice_id already reserved","value":{"code":409,"error":"history IDs already used or reservation unavailable; send not attempted","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"Internal Server Error: no WhatsApp session, client not connected, or the result could not be serialized.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"no_session":{"summary":"No WhatsApp session for this user","value":{"code":500,"error":"no session","success":false}},"client_not_connected":{"summary":"WhatsApp client disconnected","value":{"code":500,"error":"client not connected","success":false}},"serialization_failed":{"summary":"Result could not be encoded","value":{"code":500,"error":"history result serialization failed","success":false}}}}}},"502":{"description":"Bad Gateway: the history send failed or stayed unconfirmed after the IDs were reserved. Legacy envelope: top-level `success` is `true`; `data.success` is `false` and `data.result.phase` names the failing step (`validation`, `upload`, `bundle` or `notice`). Do not retry with the same IDs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupHistorySendFailureResponse"},"examples":{"notice_failed":{"summary":"Bundle acknowledged, notice failed","value":{"code":502,"data":{"success":false,"error":"history operation failed or remains unconfirmed; do not retry reserved IDs","result":{"bundle_id":"3EB0C767D26A1D6B8AA0","notice_id":"3EB0C767D26A1D6B8AA1","phase":"notice","bundle_acknowledged":true,"notice_acknowledged":false},"retry_safe":false,"recipient_delivery_verified":false,"evidence_persisted":true},"success":true}},"not_admin":{"summary":"Session is not a group admin","value":{"code":502,"data":{"success":false,"error":"history operation failed or remains unconfirmed; do not retry reserved IDs","result":{"bundle_id":"3EB0C767D26A1D6B8AB0","notice_id":"3EB0C767D26A1D6B8AB1","phase":"validation","bundle_acknowledged":false,"notice_acknowledged":false},"retry_safe":false,"recipient_delivery_verified":false,"evidence_persisted":true},"success":true}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/state":{"get":{"tags":["Business"],"summary":"Find the order state kept by the gateway","description":"Returns the same order state as `GET /business/order/state/{messageID}`, looked up by a secondary identifier instead of the received order message ID.\n\n**Features:**\n- `reference_id`: the `reference_id` of the billing that accepted the order (API or phone)\n- `order_id`: the order ID carried by the received `OrderMessage` (the `order_request_id` of the accepting billing)\n- `billing_message_id`: the WhatsApp message ID of the billing that accepted the order\n- Read-only and local: no WhatsApp request is made and no session connection is required\n\n**Rules:**\n- Exactly one of `reference_id`, `order_id` or `billing_message_id`, at most 256 bytes (`400 exactly one of messageID, reference_id, order_id or billing_message_id (at most 256 bytes) is required`)\n- `404 order state not found` when no tracked order matches for this user\n- The order lifecycle, transitions and `409` rules are described in `GET /business/order/state/{messageID}`\n","parameters":[{"name":"reference_id","in":"query","required":false,"description":"`reference_id` of the billing that accepted the order.","schema":{"type":"string","maxLength":256},"example":"order-2026-0915-001"},{"name":"order_id","in":"query","required":false,"description":"Order ID from the received `OrderMessage`.","schema":{"type":"string","maxLength":256},"example":"1976123456789012"},{"name":"billing_message_id","in":"query","required":false,"description":"WhatsApp message ID of the billing that accepted the order.","schema":{"type":"string","maxLength":256},"example":"3EB0B1C2D3E4F5A6B7C8"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Order state kept by the gateway.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Order state lookup result.","allOf":[{"$ref":"#/components/schemas/OrderStateResponse"}]}}}]},"examples":{"accepted_and_paid":{"summary":"Order accepted by the API and paid","value":{"code":200,"data":{"success":true,"seller_card_state":"local_to_acting_device","state":{"version":1,"incoming_message_id":"3EB0C767D26A1D6B8A9F","order_id":"1976123456789012","buyer":"5511999999999@s.whatsapp.net","state":"accepted","payment_status":"captured","order_status":"","billing_message_id":"3EB0B1C2D3E4F5A6B7C8","reference_id":"order-2026-0915-001","updated_at":1790000600,"history":[{"at":1790000000,"event":"received","value":"1976123456789012","source":"device","message_id":"3EB0C767D26A1D6B8A9F"},{"at":1790000300,"event":"accepted","source":"api","message_id":"3EB0B1C2D3E4F5A6B7C8"},{"at":1790000600,"event":"payment_status","value":"captured","source":"device","message_id":"3EB0A9F8E7D6C5B4A3B2"}]}},"success":true}}}}}},"400":{"description":"Invalid lookup: `exactly one of messageID, reference_id, order_id or billing_message_id (at most 256 bytes) is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"lookup_missing_or_ambiguous":{"summary":"No identifier or more than one","value":{"code":400,"error":"exactly one of messageID, reference_id, order_id or billing_message_id (at most 256 bytes) is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"No tracked order matches this identifier for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"order_state_not_found":{"summary":"Order state not found","value":{"code":404,"error":"order state not found","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The local order state could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"lookup_failed":{"summary":"Lookup failed","value":{"code":500,"error":"order state lookup failed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}},"/business/order/state/{messageID}":{"get":{"tags":["Business"],"summary":"Get the order state kept by the gateway","description":"Returns the order state this gateway keeps for a received order, like WhatsApp Web keeps its own local state.\n\nThe official WhatsApp apps keep the seller's order/billing card state (Accept/Decline buttons, \"Update status\" screen) only on the device that acted; nothing syncs it to the seller's other devices. The gateway is a linked device, so it keeps its own authoritative state and also tracks the actions the seller takes on the phone, which arrive as own messages.\n\n**Features:**\n- `state`: `received` (order message received), `accepted` (billing sent) or `rejected` (refusal sent)\n- `payment_status`: `\"\"`, `pending`, `captured` or `failed`; `order_status`: `\"\"` or the last declared lifecycle value (`preparing_to_ship`, `shipped`, `delivered`, `completed`, `canceled`, ...)\n- `billing_message_id` and `reference_id` link the billing that accepted the order\n- `history` (last 100 changes, oldest first): `at`, `event` (`received`, `accepted`, `rejected`, `payment_status`, `order_status`), `value`, `source` (`api` for this gateway, `device` for WhatsApp/the phone), `message_id`, and `note` (`out_of_order` for a phone action outside the expected order, `backfilled` for an order received before tracking started)\n- Every change emits the `OrderState` webhook event\n- Read-only and local: no WhatsApp request is made and no session connection is required\n\n**Transitions enforced on API sends** (checked before sending; nothing is sent on `409`):\n- `received` → `accepted` (`POST /business/order/accept`) or `rejected` (`POST /business/order/reject`); a second decision returns `409 order already <accepted|rejected> by message <id>; nothing sent`\n- Payment and status declarations (`/business/order/payment/status/send`, `/business/order/status/send`) on a billing linked to a tracked order require `accepted`: `409 order not accepted; nothing sent`, `409 order rejected; nothing sent`, and after `completed` or `canceled` `409 order already <completed|canceled>; nothing sent`\n- Declarations on a standalone billing (`/business/order/charge/send`) are not tracked or enforced\n- Phone actions are always recorded, never refused\n\n**Phone actions tracked** (own messages sent by another device of this account):\n- Accept: billing (`review_and_pay`) whose `order_request_id` is the order ID\n- Decline: the official refusal text `Este pedido foi recusado.` quoting the received order\n- Payment: `payment_status` declaration quoting the billing\n- Status: `review_order` declaration quoting the billing\n\n**Rules:**\n- `messageID` is the ID of the received order message (the same value used as `incoming_message_id` in accept/reject), at most 256 bytes; query lookups are not allowed together with the path (`400`)\n- `404 order state not found` when this instance never received or tracked that order for this user\n","parameters":[{"name":"messageID","in":"path","required":true,"description":"ID of the received order message (`incoming_message_id`).","schema":{"type":"string","maxLength":256},"example":"3EB0C767D26A1D6B8A9F"}],"security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Order state kept by the gateway.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"description":"Order state lookup result.","allOf":[{"$ref":"#/components/schemas/OrderStateResponse"}]}}}]},"examples":{"received":{"summary":"Order received, no decision yet","value":{"code":200,"data":{"success":true,"seller_card_state":"local_to_acting_device","state":{"version":1,"incoming_message_id":"3EB0C767D26A1D6B8A9F","order_id":"1976123456789012","buyer":"5511999999999@s.whatsapp.net","state":"received","payment_status":"","order_status":"","billing_message_id":"","reference_id":"","updated_at":1790000000,"history":[{"at":1790000000,"event":"received","value":"1976123456789012","source":"device","message_id":"3EB0C767D26A1D6B8A9F"}]}},"success":true}},"accepted_on_phone_and_shipped":{"summary":"Order accepted on the phone, then shipped","value":{"code":200,"data":{"success":true,"seller_card_state":"local_to_acting_device","state":{"version":1,"incoming_message_id":"3EB0C767D26A1D6B8A9F","order_id":"1976123456789012","buyer":"5511999999999@s.whatsapp.net","state":"accepted","payment_status":"","order_status":"shipped","billing_message_id":"3EB0B1C2D3E4F5A6B7C8","reference_id":"order-2026-0915-001","updated_at":1790000900,"history":[{"at":1790000000,"event":"received","value":"1976123456789012","source":"device","message_id":"3EB0C767D26A1D6B8A9F"},{"at":1790000300,"event":"accepted","source":"device","message_id":"3EB0B1C2D3E4F5A6B7C8"},{"at":1790000900,"event":"order_status","value":"shipped","source":"api","message_id":"3EB0D4C3B2A1F0E9D8C7"}]}},"success":true}}}}}},"400":{"description":"Invalid lookup: `exactly one of messageID, reference_id, order_id or billing_message_id (at most 256 bytes) is required`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"path_and_query_together":{"summary":"Path and query lookup together","value":{"code":400,"error":"exactly one of messageID, reference_id, order_id or billing_message_id (at most 256 bytes) is required","success":false}}}}}},"401":{"description":"Missing or invalid user token (`token` header).\n\n**Pela API pública:** Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/ErrorEnvelope"},{"$ref":"#/components/schemas/PublicApiError"}]},"examples":{"invalid_token":{"summary":"Invalid token","value":{"code":401,"error":"unauthorized","success":false}},"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"403":{"$ref":"#/components/responses/PublicApiInstanceAccessDenied"},"404":{"description":"This instance never received or tracked that order for this user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"order_state_not_found":{"summary":"Order state not found","value":{"code":404,"error":"order state not found","success":false}}}}}},"413":{"$ref":"#/components/responses/PublicApiPayloadTooLarge"},"429":{"$ref":"#/components/responses/PublicApiRateLimited"},"500":{"description":"The local order state could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"},"examples":{"lookup_failed":{"summary":"Lookup failed","value":{"code":500,"error":"order state lookup failed","success":false}}}}}},"503":{"$ref":"#/components/responses/PublicApiUnavailable"}}}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"token","description":"Token da instância (copiado na tela de integração do painel). Deixa de ser aceito quando a conta dona da instância está desativada: conta (ou Revenda) desativada → `403` com `code` `ACCOUNT_DEACTIVATED`; token não reconhecido → `401` `UNAUTHORIZED`; verificação indisponível → `503` `ACCESS_CHECK_UNAVAILABLE` com `Retry-After`. Desativar ou reativar a conta reflete na API em até 30 s."}},"schemas":{"ContextInfo":{"type":"object","description":"Optional context info for replies. When replying to a message, provide stanzaID, participant, and optionally quotedMessage for full reply preview support on all devices.","properties":{"stanzaID":{"type":"string","example":"3EB06F9067F80BAB89FF","description":"Message ID to reply to (required for replies)"},"participant":{"type":"string","example":"5511999999999@s.whatsapp.net","description":"JID of original message sender (required for replies)"},"quotedMessage":{"$ref":"#/components/schemas/QuotedMessage"},"isForwarded":{"type":"boolean","example":true,"description":"Set to true to mark the message as forwarded. This is the preferred method for forwarding messages."},"mentionedJID":{"type":"array","items":{"type":"string"},"example":["5511999999999@s.whatsapp.net","5491155553934@s.whatsapp.net"],"description":"Array of JIDs to mention in the message. Use full WhatsApp JID format (number@s.whatsapp.net)."},"mentionAll":{"type":"boolean","example":true,"description":"Set to true to mention all group members"}}},"QuotedMessage":{"type":"object","description":"The original message content being replied to. Providing this ensures proper reply preview display on all devices, especially iPhone. Without this field, replies will work but may not show the original message preview correctly on iOS devices.","properties":{"conversation":{"type":"string","example":"Hello, how are you?","description":"The text content of the original message being replied to. Use this for simple text messages."}},"example":{"conversation":"This is the original message text being replied to"}},"NetworkRouteView":{"type":"object","additionalProperties":false,"description":"Non-secret route state plus in-process readiness. Enrollment keys and SOCKS credentials are never included.","required":["mode","exitNodeId","desiredVersion","appliedVersion","failClosed","tcpOnly","status","ready"],"properties":{"mode":{"type":"string","description":"Route mode; `mobile` for stored routes, empty in the zero state of validation errors.","example":"mobile"},"exitNodeId":{"type":"string","description":"Stable Tailscale exit-node ID.","example":"nStableMobileExit01"},"desiredVersion":{"type":"integer","format":"int64","description":"Last accepted `routeVersion`.","example":3},"appliedVersion":{"type":"integer","format":"int64","description":"Last version whose node start, exit selection, loopback SOCKS and TLS preflight completed.","example":3},"failClosed":{"type":"boolean","description":"`true` holds traffic while the route is not ready; `false` lets the session use the default egress.","example":true},"tcpOnly":{"type":"boolean","description":"Always `true` for stored mobile routes (native Calls/UDP disabled).","example":true},"status":{"type":"string","description":"Stored lifecycle status; empty in the zero state of validation errors.","enum":["preparing","ready","blocked",""],"example":"ready"},"ready":{"type":"boolean","description":"`true` only when versions match, `status` is `ready` and the node for that version is live in this process.","example":true},"errorCode":{"type":"string","description":"Safe error code of the last failure; omitted when empty.","example":"network_route_prepare_failed"}}},"NetworkRouteApplyResponse":{"type":"object","description":"Success envelope of `POST` and `DELETE /session/network-route`, with `details` and `reconnectScheduled` at the top level.","required":["code","data","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":200},"data":{"$ref":"#/components/schemas/NetworkRouteView"},"details":{"type":"string","description":"`network route ready` after an apply, or the fallback explanation after a removal.","example":"network route ready"},"reconnectScheduled":{"type":"boolean","description":"`true` when the gateway queued this session to reconnect: after an apply when a previously connected session resumes on the ready route; after a removal when the session was connected or a fail-closed route that never became ready was holding it offline.","example":true},"success":{"type":"boolean","description":"Always `true`.","example":true}}},"NetworkRouteGetResponse":{"type":"object","description":"Success envelope of `GET /session/network-route`. `egressIP` or `egressProbeError` appear at the top level only with `probe=egress`.","required":["code","data","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":200},"data":{"$ref":"#/components/schemas/NetworkRouteView"},"egressIP":{"type":"string","description":"Public IP observed through the route; only when the egress probe succeeded.","example":"203.0.113.45"},"egressProbeError":{"type":"string","description":"Set instead of `egressIP` when the egress probe failed.","enum":["network_route_egress_probe_failed"],"example":"network_route_egress_probe_failed"},"success":{"type":"boolean","description":"Always `true`.","example":true}}},"NetworkRouteErrorResponse":{"type":"object","description":"Error envelope of the network-route endpoints. Errors raised by the route manager also include `data` (the stored route, or an empty state for validation errors) and, when a cause exists, a redacted `details`.","required":["code","error","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":503},"data":{"$ref":"#/components/schemas/NetworkRouteView"},"error":{"type":"string","description":"Stable machine-readable error code.","enum":["network_route_payload_invalid","network_route_mode_invalid","network_route_mobile_requires_tcp_only","network_route_version_invalid","network_route_exit_node_invalid","network_route_idempotency_key_invalid","network_route_auth_key_invalid","network_route_user_invalid","network_route_invalid","network_route_conflicts_with_proxy","network_route_stale_version","network_route_version_conflict","network_route_block_failed","network_route_not_ready","network_route_not_configured","network_route_manager_unavailable","network_route_store_unavailable","network_route_prepare_failed","network_route_restore_failed","network_route_revoke_failed","network_route_fence_lost","network_route_unavailable","network_route_ready_invariant_failed"],"example":"network_route_prepare_failed"},"details":{"type":"string","description":"Redacted cause (auth keys and URL credentials removed, at most 300 characters); omitted when there is no cause.","example":"exit node nStableMobileExit01 is offline"},"success":{"type":"boolean","description":"Always `false`.","example":false}}},"GlobalTransportSkipsRequest":{"type":"object","description":"Partial update of the per-instance global transport opt-out flags. Omitted flags keep their current value; unknown fields are ignored.","properties":{"skipGlobalWebhook":{"type":"boolean","example":false,"description":"`true` stops the global webhook from receiving this instance's events."},"skipGlobalRabbitMQ":{"type":"boolean","example":true,"description":"`true` stops the global RabbitMQ publisher from receiving this instance's events."},"skipGlobalSQS":{"type":"boolean","example":false,"description":"`true` stops the global SQS publisher from receiving this instance's events."},"skipGlobalRedis":{"type":"boolean","example":false,"description":"`true` stops the global Redis publisher from receiving this instance's events."},"skipGlobalWebSocket":{"type":"boolean","example":false,"description":"`true` stops the global WebSocket broadcaster from receiving this instance's events."},"skipGlobalS3":{"type":"boolean","example":true,"description":"`true` skips the global S3 media upload/enrichment for this instance's events."}}},"GlobalTransportSkipFlags":{"type":"object","description":"Per-instance global transport opt-out flags. `true` means the global dispatcher skips this instance for that transport.","properties":{"skipGlobalWebhook":{"type":"boolean","description":"Global webhook skipped for this instance.","example":false},"skipGlobalRabbitMQ":{"type":"boolean","description":"Global RabbitMQ skipped for this instance.","example":true},"skipGlobalSQS":{"type":"boolean","description":"Global SQS skipped for this instance.","example":false},"skipGlobalRedis":{"type":"boolean","description":"Global Redis skipped for this instance.","example":false},"skipGlobalWebSocket":{"type":"boolean","description":"Global WebSocket skipped for this instance.","example":false},"skipGlobalS3":{"type":"boolean","description":"Global S3 media enrichment skipped for this instance.","example":true}}},"GlobalTransportSkipsState":{"description":"All six opt-out flags plus a confirmation message.","allOf":[{"$ref":"#/components/schemas/GlobalTransportSkipFlags"},{"type":"object","properties":{"details":{"type":"string","description":"Human-readable confirmation.","example":"Global transport skip configuration retrieved successfully"}}}]},"GlobalTransportSkipsResponse":{"description":"Success envelope of `GET` and `POST /session/globaltransports/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/GlobalTransportSkipsState"}}}]},"EchoAPISettingsRequest":{"type":"object","description":"Per-instance API message echo flag.","properties":{"enabled":{"type":"boolean","example":true,"description":"`true` emits a `Message` event (with `Info.IsFromAPI: true`) for each message sent through the API, when `ECHO_API_MESSAGES_ENABLED` is also true. Omitted is treated as `false`."}}},"EchoAPISettingsResponse":{"description":"Success envelope of `GET /session/echo/api`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored echo flag.","properties":{"EchoAPIMessages":{"type":"boolean","description":"Whether API sends emit `Message` events for this instance.","example":true},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Echo API messages configuration retrieved successfully"}}}}}]},"GroupPhoto":{"type":"object","description":"Group and the new JPEG photo. JSON keys are matched case-insensitively.","required":["GroupJID","Image"],"properties":{"GroupJID":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"Image":{"type":"string","description":"JPEG image as a data URL (`data:image/jpeg;base64,...`). The decoded bytes must be a JPEG file.","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAD8AKp//2Q=="}}},"Connect":{"type":"object","description":"Event subscription and wait mode for `POST /session/connect` and `POST /connector/connect`. Field names are matched case-insensitively.","properties":{"Subscribe":{"type":"array","description":"Event types for the individual webhook. Replaces the stored subscription on every call; unknown names are discarded; omitted or empty stores an empty subscription. Use `[\"All\"]` for every event.","items":{"type":"string","description":"Event type name from `supportedEventTypes`.","example":"Message"},"example":["Message","ReadReceipt","Connected"]},"Immediate":{"type":"boolean","default":false,"description":"`true` returns right after starting the client. `false` waits about 10 seconds and returns 500 `failed to connect` when the socket is not connected by then.","example":true}}},"UserPresence":{"type":"object","description":"Global presence to send.","required":["type"],"properties":{"type":{"type":"string","description":"`available` (online) or `unavailable` (offline).","enum":["available","unavailable"],"example":"available"}}},"MessageContact":{"type":"object","required":["Phone","Name","Vcard"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code"},"Name":{"type":"string","example":"John Doe","description":"Contact display name"},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID"},"Vcard":{"type":"string","example":"BEGIN:VCARD\nVERSION:3.0\nN:Doe;John;;;\nFN:John Doe\nORG:Example.com Inc.;\nTITLE:Imaginary test person\nEMAIL;type=INTERNET;type=WORK;type=pref:johnDoe@example.org\nTEL;type=WORK;type=pref:+1 617 555 1212\nTEL;type=WORK:+1 (617) 555-1234\nTEL;type=CELL:+1 781 555 1212\nTEL;type=HOME:+1 202 555 1212\nitem1.ADR;type=WORK:;;2 Enterprise Avenue;Worktown;NY;01111;USA\nitem1.X-ABADR:us\nitem2.ADR;type=HOME;type=pref:;;3 Acacia Avenue;Hoitem2.X-ABADR:us\nEND:VCARD","description":"Contact information in vCard format"},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator"},"Duration":{"type":"integer","example":86400,"description":"Accepted but not applied by /chat/send/contact."},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageLocation":{"type":"object","required":["Phone","Latitude","Longitude"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code"},"Name":{"type":"string","example":"Eiffel Tower","description":"Optional location name or description"},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID"},"Latitude":{"type":"number","format":"float","example":48.85837,"description":"Latitude in decimal degrees. Exactly 0 is treated as missing (400)."},"Longitude":{"type":"number","format":"float","example":2.294481,"description":"Longitude in decimal degrees. Exactly 0 is treated as missing (400)."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator"},"Duration":{"type":"integer","example":86400,"description":"Accepted but not applied by /chat/send/location."},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"PollVote":{"type":"object","required":["phone","poll_message_id","options"],"properties":{"phone":{"type":"string","example":"5511999999999","description":"Phone number with country code, or a group JID (120363...@g.us). The vote is delivered to the chat the poll was created in."},"poll_message_id":{"type":"string","example":"90B2F8B13FAC8A9CF6B06E99C7834DC5","description":"Message ID of the poll's CREATION message (not of a vote)."},"options":{"type":"array","description":"Option names to vote for. Must match the poll's own options exactly. More than one is only valid on a multi-select poll. An EMPTY array retracts the vote.","items":{"type":"string"},"example":["09:00"]}}},"EventResponse":{"type":"object","required":["phone","event_message_id","response"],"properties":{"phone":{"type":"string","example":"5511999999999","description":"Phone number with country code, or a group JID. The RSVP is delivered to the chat the event was created in."},"event_message_id":{"type":"string","example":"90B2F8B13FAC8A9CF6B06E99C7834DC5","description":"Message ID of the event's CREATION message."},"response":{"type":"string","enum":["GOING","NOT_GOING","MAYBE","UNKNOWN"],"example":"GOING","description":"The RSVP. UNKNOWN removes a previous response. Anything outside this set is rejected with 400."},"extra_guest_count":{"type":"integer","format":"int32","default":0,"example":1,"description":"Deprecated: use with_guest. Still accepted for compatibility: 0 = no guest, >= 1 is sent as one guest (1). Only applies to GOING. Cannot be negative (400).","deprecated":true},"with_guest":{"type":"boolean","example":true,"description":"Recommended. true = \"Going with guest\" (the official app sends a single guest, extraGuestCount=1). Only applies to GOING; ignored otherwise. Takes precedence over extra_guest_count. Alias: WithGuest."}}},"MessagePoll":{"type":"object","required":["Group","Header","Options"],"properties":{"Group":{"type":"string","example":"120363000000000012@g.us","description":"Group JID where to send the poll"},"Header":{"type":"string","example":"What's your favorite color?","description":"Poll question/header text"},"Options":{"type":"array","description":"Array of poll options (minimum 2, maximum 12)","items":{"type":"string","example":"Red"},"minItems":2,"maxItems":12},"MaxAnswer":{"type":"integer","example":1,"description":"Maximum number of answers per user. If not set to 1, all options will be available for selection (accepts both 'max_answer' and 'MaxAnswer' for compatibility)"},"Id":{"type":"string","example":"3EB06F9067F80BAB89FF","description":"Optional custom message ID"},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator (accepts both 'presence' and 'Presence' for compatibility)"},"Duration":{"type":"integer","example":86400,"description":"Message expiration time in seconds (accepts both 'duration' and 'Duration' for compatibility)"},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageList":{"type":"object","required":["Phone","Text","ButtonText","Sections"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code. Must include country code without + symbol (e.g., 5511999999999)."},"Id":{"type":"string","example":"LIST_001","description":"Optional custom message ID. If not provided, a random one will be generated."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator (accepts both 'presence' and 'Presence' for compatibility)"},"Text":{"type":"string","example":"Choose one of the options below","description":"Main list description text. Maximum 1024 characters. This explains what the list is about."},"Title":{"type":"string","example":"Product Catalog","description":"Optional list title/header. Maximum 60 characters. Displayed at the top of the list."},"Footer":{"type":"string","example":"Powered by Zigzapy API","description":"Optional footer text. Maximum 60 characters. Displayed at the bottom of the list."},"ButtonText":{"type":"string","example":"View Options","description":"Text for the main action button that opens the list. Maximum 20 characters."},"Sections":{"type":"array","description":"Array of list sections. Maximum 10 sections allowed.","maxItems":10,"items":{"type":"object","required":["Title","Rows"],"properties":{"Title":{"type":"string","example":"Main Products","description":"Section title. Maximum 24 characters."},"Rows":{"type":"array","description":"Array of rows in this section. Maximum 10 rows per section.","maxItems":10,"items":{"type":"object","required":["RowId","Title","Description"],"properties":{"RowId":{"type":"string","example":"product_1","description":"Unique identifier for this row. Used in response callbacks."},"Title":{"type":"string","example":"Premium Package","description":"Row title/name. Maximum 24 characters."},"Description":{"type":"string","example":"Complete package with all features included","description":"Row description. Maximum 72 characters."}}}}}}},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageText":{"type":"object","required":["Phone","Body"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code. Must include country code without + symbol (e.g., 5511999999999)."},"Body":{"type":"string","example":"How you doin","description":"Text message content. Supports Unicode, emojis, and formatting. Maximum 4096 characters."},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID. If not provided, a random one will be generated."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator before sending message. Useful for natural conversation flow."},"Duration":{"type":"integer","example":86400,"description":"Message expiration time in seconds. Valid values: 86400 (24h), 604800 (7 days), 7776000 (90 days)."},"LinkPreview":{"type":"boolean","example":true,"description":"Set to true to enable automatic link preview for URLs in the message text."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}},"example":{"Phone":"5511999999999","Body":"This is my reply to your message","Id":"ABCDABCD1234","Presence":3000,"Duration":86400,"LinkPreview":true,"NumberCheck":true,"EchoApi":false,"ContextInfo":{"stanzaID":"3EB06F9067F80BAB89FF","participant":"5511888888888@s.whatsapp.net","quotedMessage":{"conversation":"Original message text being replied to"},"isForwarded":false,"mentionedJID":["5511999999999@s.whatsapp.net"],"mentionAll":false}}},"MessageLink":{"type":"object","required":["Phone","Link"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code. Must include country code without + symbol (e.g., 5511999999999)."},"Link":{"type":"string","example":"https://example.com","description":"Link to send. Must be a valid URL."},"Caption":{"type":"string","example":"Link Description","description":"Optional caption for the link. Supports Unicode and emojis. Required and preserved exactly, including whitespace and line breaks, when AppendLink is false."},"AppendLink":{"type":"boolean","default":true,"description":"Optional (alias: append_link). Omitted/true appends Link after Caption separated by a newline, or sends Link alone if Caption is empty. False sends Caption exactly as supplied without appending Link. Requires a nonblank Caption; with preview enabled, Link or Preview.matched_text must appear literally in Caption. With DisablePreview true, Caption need not contain the URL. Link remains required in every mode."},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID. If not provided, a random one will be generated."},"Presence":{"type":"integer","example":3000,"description":"Optional (alias: presence). Milliseconds to simulate the typing indicator before sending."},"Duration":{"type":"integer","example":86400,"description":"Optional (alias: duration). Disappearing-message expiration in seconds. Valid values: 86400 (24h), 604800 (7 days), 7776000 (90 days)."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"mention_info":{"type":"object","description":"Optional mentions without a reply. `mention_all` mentions every group participant; `mentioned_jid` (or `mentions`) lists JIDs or phone numbers to mention.","properties":{"mention_all":{"type":"boolean","example":false},"mentioned_jid":{"type":"array","items":{"type":"string"},"example":["5511999999999@s.whatsapp.net"]},"mentions":{"type":"array","items":{"type":"string"},"example":["5511999999999"]}}},"forward_info":{"type":"object","description":"Optional. Set `is_forwarded` to true to mark the message as forwarded.","properties":{"is_forwarded":{"type":"boolean","example":false}}},"DisablePreview":{"type":"boolean","example":false,"description":"Optional. Set to true to send the link as plain text without any preview card. When enabled, no auto-scrape happens and any `Preview` object is ignored. Useful when the URL is sensitive (tracker links) or when the auto-scraped preview is undesired."},"Preview":{"$ref":"#/components/schemas/LinkPreviewOverride"},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"},"context_info":{"allOf":[{"$ref":"#/components/schemas/ContextInfo"}],"description":"Snake_case alias of `ContextInfo` (reply/quote/mentions). When both are sent, `context_info` wins unless it has no `StanzaID`."}},"example":{"Phone":"5511999999999","Link":"https://example.com/promo","Caption":"Check out this deal","Id":"ABCDABCD1234","NumberCheck":false,"EchoApi":false,"DisablePreview":false,"Preview":{"title":"Coupon: 50% off everything","description":"Use code SAVE50 at checkout","image":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","matched_text":"https://example.com/promo","type":"image","fetch_missing":false}}},"LinkPreviewOverride":{"type":"object","description":"Optional custom link preview to override the default URL auto-scrape.\nWhen omitted, the link is auto-scraped for OpenGraph metadata (legacy behavior).\n\nModes (controlled by `fetch_missing`):\n- `fetch_missing` omitted or false → REPLACE mode: only the fields you set\n  are sent; no scraping is performed.\n- `fetch_missing: true` → MERGE mode: the URL is scraped first, then any\n  non-empty field you provide overrides the scraped value.\n\nTip: use REPLACE for coupon/promo links where you want full control of\nthe card; use MERGE when you only want to fix one field (e.g., image).\n","properties":{"title":{"type":"string","example":"Coupon: 50% off everything","description":"Title shown on the preview card. When an image is sent without a title (WhatsApp does not render a thumbnail card without one), the title falls back to the domain of the effective match (`matched_text` when it is a URL present in the text, otherwise `Link`). The response's `Metadata.Title` reports the title actually sent."},"description":{"type":"string","example":"Use code SAVE50 at checkout.","description":"Short description shown below the title."},"image":{"type":"string","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAUDBA... (1200x630 JPEG)","description":"Custom thumbnail that REPLACES the image WhatsApp would auto-generate\nfrom the link. Accepts a base64 data URL (≤ 5 MB) OR an http(s) URL\n(≤ 8 MB). PNG / WebP / GIF are accepted and re-encoded to JPEG\nserver-side (transparency flattened on white).\n\nTo render identically on WhatsApp **mobile AND Web/Desktop**, send the\nformat WhatsApp expects:\n• Format: JPEG (always re-encoded to JPEG; the wire field is `jpegThumbnail`).\n• Aspect ratio: 1.91:1 landscape (OpenGraph `og:image` standard).\n• Recommended size: 1200 × 630 px (min ~400 px on the long edge).\nThe server uploads a high-res JPEG (downscaled to max 800 px) AND embeds\na small inline JPEG (~200 px); Web paints the inline one first, so both\nare produced automatically — you only need to supply one good landscape\nimage. Square images ≤ 200 px are treated as favicons (smaller card).\n"},"matched_text":{"type":"string","example":"https://example.com/promo","description":"The substring of the message body that WhatsApp highlights as the\nclickable link. Defaults to `Link` if omitted. IMPORTANT: it MUST\nbe an http(s) URL that appears verbatim inside the message text —\nWhatsApp clients only attach the card when `matched_text` is a URL\nfound literally in the body (plain words such as \"click here\" drop\nthe card, validated live on iOS 2026-09-22). If the value is not a\nURL or not a substring of the text, the server falls back to `Link`. With `AppendLink: false`, that fallback is only\nvalid when `Link` appears literally in `Caption`; otherwise the\nrequest returns 400 without sending or modifying the caption.\n"},"type":{"type":"string","enum":["image","video","none","placeholder"],"default":"image","example":"image","description":"Preview card style:\n• `image` (default) — standard OpenGraph-style card with thumbnail.\n  Renders on BOTH mobile and WhatsApp Web/Desktop. (Emitted on the wire\n  as PreviewType `NONE`, which is what the official WhatsApp clients use\n  for image cards; the older `IMAGE` type did not render on Web.)\n• `video` — card with a play affordance for video links (e.g. YouTube);\n  `do_not_play_inline` controls inline playback.\n• `none` — no special preview styling (to send the link as plain text\n  with no card at all, use `DisablePreview: true`).\n• `placeholder` — neutral card without a thumbnail (opt-in; for\n  guaranteed web+mobile parity prefer `image`/`video`).\n"},"fetch_missing":{"type":"boolean","example":false,"description":"REPLACE vs MERGE switch. false/omitted = REPLACE (no scrape). true = MERGE (scrape, then override wins on non-empty fields)."},"thumbnail_width":{"type":"integer","example":1200,"description":"Optional explicit thumbnail width in pixels. When omitted, derived from the decoded image. Recommended pairing: 1200 × 630 (1.91:1)."},"thumbnail_height":{"type":"integer","example":630,"description":"Optional explicit thumbnail height in pixels. When omitted, derived from the decoded image. Recommended pairing: 1200 × 630 (1.91:1)."},"do_not_play_inline":{"type":"boolean","example":false,"description":"When `type=video`, set to true to force the WhatsApp client to open the link in the browser instead of trying to play inline."}}},"MessageImage":{"type":"object","required":["Phone","Image"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code. Must include country code without + symbol (e.g., 5511999999999)."},"Image":{"type":"string","example":"data:image/jpeg;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/5+hHgAHggJ/PchI7wAAAABJRU5ErkJggg==","description":"Image data as base64 data URL (data:image/jpeg;base64,xxx) or HTTP(S) URL (https://example.com/image.jpg). Supported formats: JPEG, PNG, GIF, WebP. Maximum size: 5MB."},"Caption":{"type":"string","example":"Image Description","description":"Optional caption for the image. Maximum 1024 characters. Supports Unicode and emojis."},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID. If not provided, a random one will be generated."},"MimeType":{"type":"string","example":"image/jpeg","description":"Optional MIME type override. Supported: image/jpeg, image/png, image/gif, image/webp. Auto-detected if not provided."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator before sending message."},"ViewOnce":{"type":"boolean","example":true,"description":"Set to true for disappearing message after viewing (view once). Cannot be combined with Duration."},"Duration":{"type":"integer","example":86400,"description":"Message expiration time in seconds. Valid values: 86400 (24h), 604800 (7 days), 7776000 (90 days)."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageAudio":{"type":"object","required":["Phone","Audio"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code. Must include country code without + symbol (e.g., 5511999999999)."},"Audio":{"type":"string","example":"data:audio/ogg;base64,T2dnUwACAAAAAAAAAABK","description":"Audio data as base64 data URL (data:audio/ogg;base64,xxx) or HTTP(S) URL (https://example.com/audio.ogg). Supported formats: OGG, MP3, AAC, M4A, WAV. Maximum size: 16MB."},"Caption":{"type":"string","example":"Voice message caption","description":"Accepted for compatibility but not delivered: WhatsApp audio messages have no caption."},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID. If not provided, a random one will be generated."},"PTT":{"type":"boolean","example":true,"description":"Set to true for voice note (push-to-talk), false for audio file. Voice notes show with different UI and waveform. Default: true."},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate recording indicator before sending message. Useful for natural conversation flow."},"ViewOnce":{"type":"boolean","example":true,"description":"Set to true for disappearing message after viewing (view once). Cannot be combined with Duration."},"Duration":{"type":"integer","example":86400,"description":"Message expiration time in seconds. Valid values: 86400 (24h), 604800 (7 days), 7776000 (90 days)."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageVideo":{"type":"object","required":["Phone","Video"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code (accepts both 'phone' and 'Phone' for compatibility)"},"Video":{"type":"string","example":"data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDE=","description":"Video data as base64 data URL (data:video/mp4;base64,xxx) or HTTP(S) URL (https://example.com/video.mp4) (accepts both 'video' and 'Video' for compatibility)"},"Caption":{"type":"string","example":"my video","description":"Optional caption for the video (accepts both 'caption' and 'Caption' for compatibility)"},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID (accepts both 'id' and 'Id' for compatibility)"},"MimeType":{"type":"string","example":"video/mp4","description":"Optional MIME type override (video/mp4, video/3gpp, video/quicktime, video/x-ms-asf) (accepts both 'mimetype' and 'MimeType' for compatibility)"},"JPEGThumbnail":{"type":"string","format":"byte","description":"Optional JPEG thumbnail as plain base64 (no data: prefix). Generated from the video when omitted. Accepts `jpeg_thumbnail` or `JPEGThumbnail`.","example":"/9j/4AAQSkZJRgABAQEASABIAAD/wAARCAABAAEBAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACP/aAAgBAQAAPwAA/9k="},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator"},"ViewOnce":{"type":"boolean","example":true,"description":"Set to true for disappearing message after viewing (accepts both 'view_once' and 'ViewOnce' for compatibility)"},"Duration":{"type":"integer","example":86400,"description":"Message expiration time in seconds (accepts both 'duration' and 'Duration' for compatibility)"},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessagePTV":{"type":"object","required":["Phone","Video"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code (accepts both 'phone' and 'Phone' for compatibility)"},"Video":{"type":"string","example":"data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDE=","description":"Video data as base64 data URL (data:video/mp4;base64,xxx) or HTTP(S) URL (https://example.com/video.mp4) for PTV message (accepts both 'video' and 'Video' for compatibility)"}}},"MessageEvent":{"type":"object","required":["Phone","Name","StartTime"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code. Must include country code without + symbol (e.g., 5511999999999)."},"Name":{"type":"string","example":"Team Meeting","description":"Event title/name. Maximum 255 characters."},"Description":{"type":"string","example":"Weekly team sync meeting to discuss project updates","description":"Optional detailed event description. Maximum 1024 characters. Supports Unicode and emojis."},"StartTime":{"type":"integer","format":"int64","example":2524608000,"description":"Event start time as Unix timestamp (seconds since epoch). Required field."},"EndTime":{"type":"integer","format":"int64","example":2556143999,"description":"Event end time as Unix timestamp (seconds since epoch). Optional, but recommended."},"ExtraGuestsAllowed":{"type":"boolean","example":true,"description":"Set to true to allow participants to invite additional guests to the event."},"IsCanceled":{"type":"boolean","example":false,"description":"Set to true to mark the event as cancelled. Default: false."},"IsScheduleCall":{"type":"boolean","example":true,"description":"Set to true if this is a scheduled call event (video/voice meeting)."},"Id":{"type":"string","example":"EVENT_001","description":"Optional custom message ID. If not provided, a random one will be generated."},"Presence":{"type":"integer","example":2000,"description":"Milliseconds to simulate typing indicator before sending event."},"NumberCheck":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"Location":{"type":"object","description":"Optional event location details with GPS coordinates.","properties":{"Name":{"type":"string","example":"Conference Room A, Main Office","description":"Location name or address. Maximum 255 characters."},"DegreesLatitude":{"type":"number","format":"float","example":-23.5505,"description":"Latitude coordinate for the location (GPS)."},"DegreesLongitude":{"type":"number","format":"float","example":-46.6333,"description":"Longitude coordinate for the location (GPS)."}}},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"ButtonsMessage":{"type":"object","description":"Interactive message with buttons.","required":["phone","title","buttons"],"properties":{"phone":{"type":"string","example":"5511999999999","description":"Recipient phone number with country code (without +) or group JID (e.g., 120363000000000011@g.us)."},"title":{"type":"string","minLength":1,"maxLength":60,"example":"PIX payment","description":"Required heading displayed above the body. Must contain 1 to 60 characters. Do not send a whitespace-only value because WhatsApp will render an empty header area."},"body":{"type":"string","example":"Scan the QR code to pay with PIX","description":"Primary message text. Use this or text when not sending media headers."},"text":{"type":"string","example":"Choose an option below","description":"Alternative field for the primary text. When media headers are present, prefer caption/text over body."},"footer":{"type":"string","example":"Zigzapy team","description":"Optional footer text displayed below the buttons."},"caption":{"type":"string","example":"Deal of the week","description":"Optional media caption when using image/video/document headers."},"image":{"type":"object","description":"Optional image header.","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://picsum.photos/600/400.jpg","description":"HTTP(S) or data URL pointing to the image."}}},"video":{"type":"object","description":"Optional video header.","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://download.blender.org/durian/trailer/sintel_trailer-480p.mp4","description":"HTTP(S) or data URL pointing to the video file."}}},"document":{"type":"object","description":"Optional document header (PDF, DOC, etc.).","required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf","description":"HTTP(S) or data URL pointing to the document."}}},"buttons":{"type":"array","description":"1 to 3 interactive buttons (`400 3 buttons is the limit` above 3). A reply/quick_reply button cannot be mixed with other button types.","minItems":1,"maxItems":3,"items":{"type":"object","required":["buttonId","buttonText","type"],"properties":{"buttonId":{"type":"string","example":"pix_btn_1","description":"Unique button identifier returned in callbacks."},"buttonText":{"type":"object","description":"Label configuration for the button.","required":["displayText"],"properties":{"displayText":{"type":"string","example":"Pay with PIX","description":"Button label shown to end users, 1-30 characters (`400 text can´t be null` / `text max 30 characters`).","maxLength":30}}},"type":{"type":"string","enum":["quick_reply","reply","url","cta_url","call","cta_call","copy","cta_copy","pix","pix_payment","payment_info","review_and_pay"],"example":"pix","description":"Button action type. Use `pix`/`payment_info` for PIX payments, `review_and_pay` for order payments, and quick_reply/cta_* for interactive actions."},"url":{"type":"string","format":"uri","example":"https://example.com/offer","description":"Destination URL for url/cta_url buttons."},"merchant_url":{"type":"string","format":"uri","example":"https://store.example.com/checkout","description":"Alternative merchant URL for url buttons."},"phone":{"type":"string","example":"+5511988888888","description":"Phone number in E.164 format for call/cta_call buttons."},"code":{"type":"string","example":"COUPON123","description":"Coupon or code copied when using copy/cta_copy buttons."},"pix_key":{"type":"string","example":"11999999999","description":"PIX key for pix/payment_info/review_and_pay buttons."},"merchant_name":{"type":"string","example":"Example Store","description":"Merchant name shown on PIX/review_and_pay buttons."},"pix_type":{"type":"string","example":"PHONE","enum":["PHONE","EMAIL","CPF","CNPJ","EVP"],"description":"Type of PIX key provided in pix_key."},"currency":{"type":"string","example":"BRL","description":"Currency code (ISO 4217) for review_and_pay buttons."},"total_value":{"type":"integer","example":2599,"description":"Total amount in minor units (e.g., cents) for review_and_pay buttons."},"total_offset":{"type":"integer","example":100,"description":"Optional offset or discount amount in minor units."},"reference_id":{"type":"string","example":"ORDER-2024-001","description":"Reference identifier associated with the payment/order."},"items":{"type":"array","description":"Detailed order items for review_and_pay buttons.","items":{"type":"object","required":["name","quantity","amount_value","amount_offset"],"properties":{"name":{"type":"string","example":"Headphones","description":"Item name."},"quantity":{"type":"integer","example":1,"description":"Quantity of the item."},"amount_value":{"type":"integer","example":7990,"description":"Item value in minor units (e.g., cents)."},"amount_offset":{"type":"integer","example":100,"description":"Optional discount/offset in minor units for the item."}}}}}}},"id":{"type":"string","example":"3EB0C767D26A1D6B8A9F","description":"Optional custom message ID. If not provided, a random one will be generated."},"presence":{"type":"integer","example":2000,"description":"Milliseconds to simulate typing indicator before sending the message."},"duration":{"type":"integer","example":10,"description":"Ephemeral duration for the message (when applicable)."},"number_check":{"type":"boolean","example":true,"description":"Set to true to verify if the phone number is registered on WhatsApp before sending."},"context_info":{"$ref":"#/components/schemas/ContextInfo"}}},"FlowMessage":{"type":"object","description":"Native flow interactive message.","required":["Phone","Buttons"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Recipient phone number with country code (without +) or group JID."},"Body":{"type":"string","example":"Complete your profile to unlock premium features","description":"Primary message text. Use this or Text/Message."},"Text":{"type":"string","example":"Complete your profile to unlock premium features","description":"Alternative body text."},"Message":{"type":"string","example":"Complete your profile to unlock premium features","description":"Legacy body text field."},"Caption":{"type":"string","example":"Let's get started","description":"Optional caption when using media headers."},"Footer":{"type":"string","example":"Powered by Zigzapy","description":"Optional footer text."},"Id":{"type":"string","example":"FLOW_MSG_001","description":"Custom message ID. Auto-generated when omitted."},"Presence":{"type":"integer","example":2000,"description":"Typing simulation in milliseconds before sending."},"NumberCheck":{"type":"boolean","example":true,"description":"Verify that the recipient is registered on WhatsApp before sending."},"MessageVersion":{"type":"integer","format":"int32","example":3,"description":"Native flow message version. Use the latest available version."},"MessageParams":{"type":"object","description":"Flow parameters as an object. Use MessageParams or MessageParamsJSON.","additionalProperties":true,"example":{"flow_type":"registration","required_fields":["name","email"]}},"MessageParamsJSON":{"type":"string","example":"{\"flow_type\":\"registration\"}","description":"Flow parameters represented as a JSON string."},"Header":{"type":"object","description":"Optional header with title, subtitle, and media.","properties":{"Title":{"type":"string","example":"Complete your profile","description":"Header title."},"Subtitle":{"type":"string","example":"Only takes 2 minutes","description":"Header subtitle."},"Media":{"type":"object","properties":{"Type":{"type":"string","enum":["image","video","document"],"example":"image","description":"Header media type."},"Url":{"type":"string","example":"https://example.com/header.png","description":"Media URL or base64 data URL."},"Caption":{"type":"string","example":"Preview","description":"Media caption."},"Filename":{"type":"string","example":"guide.pdf","description":"File name for document media."},"MimeType":{"type":"string","example":"image/png","description":"MIME type of the media."}},"description":"Optional header media."}}},"Buttons":{"type":"array","description":"Array of native flow buttons.","minItems":1,"items":{"type":"object","required":["Name"],"properties":{"Name":{"type":"string","example":"complete_profile","description":"Button identifier."},"ButtonParams":{"type":"object","description":"Button parameters as an object.","additionalProperties":true,"example":{"display_text":"Complete Profile","flow_id":"123456789"}},"ButtonParamsJSON":{"type":"string","example":"{\"display_text\":\"Complete Profile\",\"flow_id\":\"123456789\"}","description":"Button parameters as JSON string."},"Params":{"type":"object","description":"Optional flow parameters object.","additionalProperties":true,"example":{"mode":"draft","version":"3.0"}},"ParamsJSON":{"type":"string","example":"{\"mode\":\"published\",\"version\":\"3.0\"}","description":"Optional flow parameters JSON string."}}}},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"CarouselMessage":{"type":"object","description":"Carousel message with multiple cards.","required":["Phone","Message","Carousel"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Recipient phone number with country code (without +) or group JID."},"Message":{"type":"string","example":"Check out our featured products!","description":"Introductory text shown before the carousel cards."},"Carousel":{"type":"array","description":"Array of carousel card objects.","minItems":1,"maxItems":10,"items":{"type":"object","required":["Text","Buttons"],"properties":{"Text":{"type":"string","example":"Premium Wireless Headphones\n\n• Noise cancellation\n• 30h battery\n• Premium sound\n\n$299.99","description":"Card body text."},"MediaUrl":{"type":"string","example":"https://picsum.photos/600/400.jpg","description":"Optional media URL or base64 data URL."},"MediaType":{"type":"string","enum":["image","video","document"],"example":"image","description":"Media type required when MediaUrl is provided."},"Filename":{"type":"string","example":"Product_Guide.pdf","description":"Optional filename for document media."},"Caption":{"type":"string","example":"Best Seller!","description":"Optional media caption."},"Buttons":{"type":"array","description":"Card-specific buttons.","minItems":1,"maxItems":3,"items":{"type":"object","required":["Label","Type"],"properties":{"Id":{"type":"string","example":"buy_headphones","description":"Button identifier for reply/copy buttons."},"Label":{"type":"string","example":"Buy Now","description":"Button display text."},"Url":{"type":"string","example":"https://store.example.com/product/123","description":"Destination URL for url buttons."},"Type":{"type":"string","enum":["reply","url","copy","call"],"example":"url","description":"Button type."}}}}}}},"Id":{"type":"string","example":"CAROUSEL_MSG_001","description":"Custom message ID. Auto-generated when omitted."},"Presence":{"type":"integer","example":2000,"description":"Typing simulation in milliseconds before sending."},"NumberCheck":{"type":"boolean","example":true,"description":"Verify that the recipient is registered on WhatsApp before sending."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageSticker":{"type":"object","required":["Phone","Sticker"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code"},"Sticker":{"type":"string","example":"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=","description":"Sticker data as base64 data URL (data:image/webp;base64,xxx) or HTTP(S) URL (https://example.com/sticker.webp)"},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID"},"MimeType":{"type":"string","example":"image/webp","description":"Optional MIME type override (image/webp, image/jpeg, image/png, image/gif)"},"PngThumbnail":{"type":"string","format":"byte","description":"Optional PNG thumbnail as base64 string","example":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"MessageDocument":{"type":"object","required":["Phone","Document","FileName"],"properties":{"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code"},"Document":{"type":"string","example":"data:application/pdf;base64,JVBERi0xLjQKJcOkw7zDtsO...","description":"Document data as base64 data URL (data:application/pdf;base64,xxx) or HTTP(S) URL (https://example.com/document.pdf)"},"FileName":{"type":"string","example":"document.pdf","description":"Name of the document file with extension"},"Caption":{"type":"string","example":"Important document","description":"Optional caption for the document"},"Id":{"type":"string","example":"ABCDABCD1234","description":"Optional custom message ID"},"MimeType":{"type":"string","example":"application/pdf","description":"Optional MIME type override (application/pdf, application/msword, text/plain, etc.)"},"Presence":{"type":"integer","example":3000,"description":"Milliseconds to simulate typing indicator"},"Duration":{"type":"integer","example":86400,"description":"Message expiration time in seconds"},"EchoApi":{"type":"boolean","example":true,"description":"Optional. Set to true to force emission of API echo events for this specific message, regardless of global or per-session echo settings. When enabled, a synthetic Message event with Info.IsFromAPI=true will be emitted through your configured transports/webhook after the message is successfully sent. This allows individual message-level control over echo behavior, overriding both ECHO_API_MESSAGES_ENABLED (global) and the per-session echo_api_messages setting. Useful for selectively tracking specific API-sent messages through your event pipeline."},"ContextInfo":{"$ref":"#/components/schemas/ContextInfo"}}},"Pairphone":{"type":"object","description":"Phone number and device label for code pairing (`POST /session/pairphone`, `POST /connector/pairphone`).","required":["Phone"],"properties":{"Phone":{"type":"string","description":"Phone number with country code, digits only (no `+`).","example":"5511999999999"},"client_type":{"type":"string","description":"Device label shown on the phone next to the linking code. Case-insensitive; omitted or empty means `chrome` (\"Chrome (Linux)\").","enum":["unknown","chrome","edge","firefox","ie","opera","safari","electron","uwp","otherwebclient","macos","android"],"example":"chrome"}}},"StickerPack":{"type":"object","description":"Public sticker pack as returned by `GET /business/sticker-pack/{packId}` (inside the gateway envelope `data`).","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"id":{"type":"string","description":"Pack ID.","example":"8e2a3c1f4b5d6e7f8a9b0c1d2e3f4a5b"},"name":{"type":"string","description":"Pack name.","example":"Cute Cats"},"publisher":{"type":"string","description":"Publisher name.","example":"Acme Stickers"},"description":{"type":"string","description":"Pack description.","example":"A pack of expressive cat stickers."},"file_size":{"type":"string","description":"Total pack size in bytes, as a string.","example":"1238423"},"image_data_hash":{"type":"string","description":"Pack image data hash.","example":"f31a4c9e8d7b6a5f4e3d2c1b0a9f8e7d"},"animated":{"type":"integer","description":"1 when the pack is animated, otherwise 0.","example":0},"lottie":{"type":"integer","description":"1 when the pack uses Lottie stickers, otherwise 0.","example":0},"preview_image_ids":{"type":"array","description":"Preview image IDs.","items":{"type":"string"},"example":["1.webp","2.webp"]},"tray_image_id":{"type":"string","description":"Tray icon image ID.","example":"tray.png"},"tray_image_preview":{"type":"string","description":"Base64 tray icon preview.","example":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="},"stickers":{"type":"array","description":"Stickers of the pack.","items":{"$ref":"#/components/schemas/StickerPackItem"}},"sticker_count":{"type":"integer","description":"Number of stickers returned.","example":1}}},"StickerPackItem":{"type":"object","description":"One sticker with the fields required by `/chat/downloadsticker`.","properties":{"url":{"type":"string","description":"Media URL.","example":"https://mmg.whatsapp.net/v/t62.15575-24/example-sticker.webp"},"direct_path":{"type":"string","description":"Media direct path.","example":"/v/t62.15575-24/example-sticker.webp"},"media_key":{"type":"string","description":"Media key (hex).","example":"5f1d0c2b9a8e7f6d5c4b3a2918070605f4e3d2c1b0a998877665544332211000"},"file_hash":{"type":"string","description":"SHA-256 of the plaintext file (hex).","example":"a3f1c2d4e5b60718293a4b5c6d7e8f90a1b2c3d4e5f60718293a4b5c6d7e8f90"},"file_enc_hash":{"type":"string","description":"SHA-256 of the encrypted file (hex).","example":"b4e2d3c5f6a70819203b4c5d6e7f8091b2c3d4e5f6a70819203b4c5d6e7f8091"},"file_size":{"type":"integer","description":"File size in bytes.","example":24576},"mimetype":{"type":"string","description":"MIME type.","example":"image/webp"},"width":{"type":"integer","description":"Width in pixels.","example":512},"height":{"type":"integer","description":"Height in pixels.","example":512},"emojis":{"type":"array","description":"Emojis associated with the sticker.","items":{"type":"string"},"example":["😺"]},"accessibility_text":{"type":"string","description":"Accessibility label.","example":"Smiling orange cat"},"handle":{"type":"string","description":"Sticker handle inside the pack.","example":"01"},"sticker_hash_without_meta":{"type":"string","description":"Sticker hash without metadata (hex).","example":"c5f3e4d6a7b8091a2b3c4d5e6f708192c3d4e5f6a7b8091a2b3c4d5e6f708192"},"preview_webp_id":{"type":"string","description":"Preview image ID.","example":"1_preview.webp"}}},"Checkuser":{"type":"object","description":"Phone numbers to check.","required":["Phone"],"properties":{"Phone":{"type":"array","description":"Phone numbers in international format, without `+`. Must be an array with at least one item.","minItems":1,"items":{"type":"string","description":"Phone number with country code.","example":"5511999999999"},"example":["5511999999999","5511988888888"]}}},"Checkavatar":{"type":"object","description":"Account whose profile picture is requested, plus optional access context.","required":["Phone"],"properties":{"Phone":{"type":"string","description":"Phone number, user JID, group JID or community JID.","example":"5511999999999"},"Preview":{"type":"boolean","default":false,"description":"`true` returns the thumbnail, `false` the full-resolution picture.","example":true},"IsCommunity":{"type":"boolean","default":false,"description":"Set to `true` when `Phone` is a community JID.","example":false},"CommonGID":{"type":"string","description":"Group JID shared with the account, used as access context for privacy-restricted pictures.","example":"120363000000000011@g.us"},"InviteCode":{"type":"string","description":"Group invite code, to read a group picture before joining.","example":"AbCdEfGhIjKlMnOpQrStUv"},"PersonaID":{"type":"string","description":"Meta AI persona ID, to read a bot persona picture.","example":"867051314767696"}}},"WebhookSet":{"type":"object","description":"Individual webhook URL and optional event subscription.","properties":{"webhookurl":{"type":"string","description":"URL that receives the events, stored without validation. Empty or omitted clears the webhook.","example":"https://example.com/webhooks/whatsapp"},"events":{"type":"array","description":"Event types to subscribe to (case-sensitive, see `GET /webhook` for the full list, `All` for every type). Unknown names are discarded. When omitted or empty, the stored subscription is kept.","items":{"type":"string","description":"Canonical event type name.","example":"Message"},"example":["Message","ReadReceipt","Connected"]}}},"WebhookUpdate":{"type":"object","description":"Individual webhook URL, event subscription and activation switch.","properties":{"webhookurl":{"type":"string","description":"URL that receives the events, stored without validation. Ignored (stored empty) when `active` is false.","example":"https://example.com/webhooks/whatsapp"},"events":{"type":"array","description":"Event types to subscribe to (trimmed, case-sensitive, see `GET /webhook`). Unknown names are discarded. When omitted or empty, the stored subscription is kept.","items":{"type":"string","description":"Canonical event type name.","example":"Message"},"example":["Message","ReadReceipt"]},"active":{"type":"boolean","default":false,"description":"`true` keeps the webhook active. Omitted or `false` clears the stored URL (and the subscription when `events` is sent).","example":true}}},"GroupLeave":{"type":"object","description":"Group to leave. JSON keys are matched case-insensitively.","required":["GroupJID"],"properties":{"GroupJID":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"}}},"GroupName":{"type":"object","description":"Group and its new name. JSON keys are matched case-insensitively.","required":["GroupJID","Name"],"properties":{"GroupJID":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"Name":{"type":"string","minLength":1,"description":"New group subject. Must not be empty; WhatsApp enforces the maximum length.","example":"Customer Success Team"}}},"GroupTopic":{"type":"object","description":"Group and its new description. JSON keys are matched case-insensitively.","required":["GroupJID","Topic"],"properties":{"GroupJID":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"Topic":{"type":"string","minLength":1,"description":"New group description. Must not be empty; WhatsApp enforces the maximum length.","example":"Support hours: Mon-Fri, 9am-6pm."}}},"GroupAnnounce":{"type":"object","description":"Group and its announce setting. JSON keys are matched case-insensitively.","required":["GroupJID"],"properties":{"GroupJID":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"Announce":{"type":"boolean","default":false,"description":"`true` lets only admins send messages; `false` (or omitted) lets every member send.","example":true}}},"GroupJoin":{"type":"object","description":"Invite code used to join a group. JSON keys are matched case-insensitively.","required":["Code"],"properties":{"Code":{"type":"string","description":"Invite code, or the full `https://chat.whatsapp.com/<code>` link.","example":"AbCdEfGhIjKlMnOpQrStUv"}}},"GroupInviteInfo":{"type":"object","description":"Invite code of the group to preview. JSON keys are matched case-insensitively.","required":["Code"],"properties":{"Code":{"type":"string","description":"Invite code, or the full `https://chat.whatsapp.com/<code>` link.","example":"AbCdEfGhIjKlMnOpQrStUv"}}},"UpdateGroupParticipants":{"type":"object","description":"Group, people and the action to apply. JSON keys are matched case-insensitively; `Action` values are not.","required":["GroupJID","Phone","Action"],"properties":{"GroupJID":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"Phone":{"type":"array","minItems":1,"description":"People to change. Phone numbers with country code or user JIDs (`@s.whatsapp.net` / `@lid`).","items":{"type":"string","description":"Phone number or user JID.","example":"5511999999999"},"example":["5511999999999","5511988888888"]},"Action":{"type":"string","description":"Action applied to every entry in `Phone`.","enum":["add","remove","promote","demote"],"example":"add"}}},"CreateGroup":{"type":"object","description":"Name and initial participants of a new group. JSON keys are matched case-insensitively.","required":["Name","Participants"],"properties":{"Name":{"type":"string","minLength":1,"description":"Group subject. Must not be empty.","example":"Project Team"},"Participants":{"type":"array","minItems":1,"description":"People to add. Phone numbers with country code (no `+`) or user JIDs (`@s.whatsapp.net` / `@lid`).","items":{"type":"string","description":"Phone number or user JID.","example":"5511999999999"},"example":["5511999999999","5511988888888"]}}},"GroupLocked":{"type":"object","description":"Group and its locked setting. JSON keys are matched case-insensitively.","required":["groupjid"],"properties":{"groupjid":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"locked":{"type":"boolean","default":false,"description":"`true` lets only admins edit group info; `false` (or omitted) lets every member edit it.","example":true}}},"GroupEphemeral":{"type":"object","description":"Group and its disappearing messages timer. JSON keys are matched case-insensitively.","required":["groupjid","duration"],"properties":{"groupjid":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"},"duration":{"type":"string","description":"Timer for new messages. `off` disables disappearing messages.","enum":["24h","7d","90d","off"],"example":"7d"}}},"GroupMemberAddMode":{"type":"object","description":"Group and the new \"Add other members\" permission.","required":["groupjid","mode"],"properties":{"groupjid":{"type":"string","description":"Group JID (`@g.us`). Key is case-insensitive.","example":"120363000000000011@g.us"},"mode":{"type":"string","description":"`admin_add` lets only admins add members; `all_member_add` lets every member add members.","enum":["admin_add","all_member_add"],"example":"admin_add"}}},"GroupJoinApproval":{"type":"object","description":"Group and whether new members need admin approval.","required":["groupjid"],"properties":{"groupjid":{"type":"string","description":"Group JID (`@g.us`). Key is case-insensitive.","example":"120363000000000011@g.us"},"require_approval":{"type":"boolean","default":false,"description":"`true` makes new members wait for admin approval; `false` (or omitted) lets them join directly.","example":true}}},"RemoveGroupPhoto":{"type":"object","description":"Group whose photo is removed. JSON keys are matched case-insensitively.","required":["groupjid"],"properties":{"groupjid":{"type":"string","description":"Group JID (`@g.us`).","example":"120363000000000011@g.us"}}},"SessionStatus":{"type":"object","description":"Connection, pairing and configuration snapshot of the instance returned by `GET /session/status`.","required":["id","connected","loggedIn","hasClient","connectionHealth","timestamp"],"properties":{"id":{"type":"string","description":"Instance (user) ID.","example":"bec45bb93cbd24cbec32941ec3c93a12"},"name":{"type":"string","description":"Instance name.","example":"Support Line"},"avatar_url":{"type":"string","description":"Profile picture URL from the 24-hour cache; empty when unknown.","example":"https://pps.whatsapp.net/v/t61.24694-24/example_avatar.jpg"},"connected":{"type":"boolean","description":"Whether the WhatsApp socket is connected.","example":true},"loggedIn":{"type":"boolean","description":"Whether the device is paired and authenticated.","example":true},"hasClient":{"type":"boolean","description":"Whether a client exists in memory for the instance.","example":true},"connectionHealth":{"type":"string","description":"Summary derived from `hasClient`, `connected` and `loggedIn`.","enum":["no_client","disconnected","connected_not_logged","connected"],"example":"connected"},"lastSuccessfulConnect":{"type":"integer","format":"int64","description":"Unix time of the last successful connection; 0 without a client.","example":1757862000},"autoReconnectErrors":{"type":"integer","description":"Consecutive failed automatic reconnect attempts.","example":0},"enableAutoReconnect":{"type":"boolean","description":"Whether automatic reconnect is enabled on the client.","example":true},"expiration":{"type":"integer","format":"int64","description":"Seconds until the stored expiration timestamp (negative when already past or unset).","example":86400},"token":{"type":"string","description":"Instance token. Removed on `GET /connector/status`.","example":"a1b2c3d4e5f6a7b8c9d0"},"jid":{"type":"string","description":"Device JID; empty before pairing.","example":"5511999999999:12@s.whatsapp.net"},"webhook":{"type":"string","description":"Individual webhook URL. Removed on `GET /connector/status`.","example":"https://example.com/webhook"},"events":{"type":"string","description":"Comma-separated individual webhook subscription. Removed on `GET /connector/status`.","example":"Message,ReadReceipt"},"proxy_url":{"type":"string","description":"Legacy proxy URL from the user cache. Removed on `GET /connector/status`.","example":""},"qrcode":{"type":"string","description":"Pending QR code as a PNG data URL; empty when none is pending.","example":""},"skip_media_download":{"type":"boolean","description":"Media is not downloaded for events.","example":false},"skip_groups":{"type":"boolean","description":"Group events are skipped.","example":false},"skip_newsletters":{"type":"boolean","description":"Newsletter events are skipped.","example":false},"skip_broadcasts":{"type":"boolean","description":"Broadcast and status events are skipped.","example":true},"skip_own_messages":{"type":"boolean","description":"Messages sent by this account are skipped.","example":false},"echo_api_messages":{"type":"boolean","description":"Messages sent through the API are echoed to transports.","example":false},"skip_calls":{"type":"boolean","description":"Call events are skipped (and calls are rejected when configured).","example":false},"call_reject_message":{"type":"string","description":"Text sent when a call is rejected automatically.","example":"Sorry, I cannot take calls at the moment."},"call_reject_type":{"type":"string","description":"Automatic call rejection mode as stored.","example":"busy"},"globalTransportSkips":{"$ref":"#/components/schemas/SessionStatusTransportSkips"},"isFromAPI":{"type":"boolean","description":"Same value as `echo_api_messages`.","example":false},"auto_presence_unavailable":{"type":"boolean","description":"Whether the client marks itself unavailable automatically after connecting.","example":false},"proxy_config":{"$ref":"#/components/schemas/ProxyConfig"},"s3_config":{"$ref":"#/components/schemas/SessionStatusS3Config"},"rabbitmq_config":{"$ref":"#/components/schemas/SessionStatusRabbitMQConfig"},"passkeyRequired":{"type":"boolean","description":"`true` while a passkey challenge is stored and not confirmed.","example":false},"passkeyResponseSubmitted":{"type":"boolean","description":"Whether a WebAuthn response was already submitted.","example":false},"passkeyConfirmed":{"type":"boolean","description":"Whether the passkey pairing was confirmed.","example":false},"passkeyConfirmationCode":{"type":"string","description":"Confirmation code to compare with the phone; empty until WhatsApp sends it.","example":""},"passkeySkipHandoffUX":{"type":"boolean","description":"`true` when WhatsApp does not require the code comparison (the gateway confirms automatically).","example":false},"passkeyError":{"type":"string","description":"Last passkey error text; empty when none.","example":""},"timestamp":{"type":"integer","format":"int64","description":"Unix time when the snapshot was built.","example":1757865600}}},"ProxyConfig":{"type":"object","description":"Proxy block of the session status.","required":["enabled"],"properties":{"enabled":{"type":"boolean","description":"`true` when a proxy URL is stored.","example":false},"proxy_url":{"type":"string","description":"Stored proxy URL, credentials included; empty when none.","example":""}}},"SkipMediaConfig":{"type":"object","description":"Per-instance media download skip flag.","properties":{"enabled":{"type":"boolean","description":"`true` skips media download for message events (metadata only, no base64, no S3 upload); `false` downloads media. Omitted is treated as `false`.","example":true}}},"SkipGroupsConfig":{"type":"object","description":"Per-instance group events skip flag.","properties":{"enabled":{"type":"boolean","description":"`true` drops every event from `@g.us` group chats before processing; `false` processes them. Omitted is treated as `false`.","example":true}}},"SkipNewslettersConfig":{"type":"object","description":"Per-instance newsletter (Channels) events skip flag.","properties":{"enabled":{"type":"boolean","description":"`true` drops every event from `@newsletter` chats and newsletter follow/mute/live updates; `false` processes them. Omitted is treated as `false`.","example":true}}},"SkipBroadcastsConfig":{"type":"object","description":"Per-instance broadcast and Status events skip flag.","properties":{"enabled":{"type":"boolean","description":"`true` drops message, receipt and presence events from `@broadcast` chats, including `status@broadcast`; `false` processes them. Omitted is treated as `false`.","example":true}}},"SkipCallsConfig":{"type":"object","description":"Per-instance automatic call rejection settings.","properties":{"enabled":{"type":"boolean","description":"`true` rejects incoming calls automatically and drops call offer events; `false` lets calls ring. Omitted is treated as `false`.","example":true},"reject_message":{"type":"string","description":"Text message sent to the caller after the rejection. Empty or omitted is stored as `Sorry, I cannot take calls at the moment.`","example":"Sorry, I cannot take calls right now. Please send a message."},"reject_type":{"type":"string","description":"Stored rejection label. Empty or omitted is stored as `busy`. It does not change the rejection sent to WhatsApp.","enum":["busy","declined","unavailable"],"example":"busy"}}},"SkipOwnMessagesConfig":{"type":"object","description":"Per-instance own-message events skip flag.","properties":{"enabled":{"type":"boolean","description":"`true` drops events about messages sent by this account (`IsFromMe`); `false` processes them. Omitted is treated as `false`.","example":true}}},"MessageEdit":{"type":"object","required":["Id","Phone","Body"],"properties":{"Id":{"type":"string","example":"90B2F8B13FAC8A9CF6B06E99C7834DC5","description":"Message ID to edit. A text message, or an image/video/document whose caption you want to change — the type is detected automatically."},"Phone":{"type":"string","example":"5511999999999","description":"Phone number with country code"},"Body":{"type":"string","example":"This is the updated message","description":"New message content: the new text for a text message, or the new caption for an image/video/document."},"ContextInfo":{"type":"object","description":"Optional context info for replies","properties":{"StanzaId":{"type":"string","example":"3EB06F9067F80BAB89FF","description":"Message ID to reply to"},"Participant":{"type":"string","example":"5511999999999@s.whatsapp.net","description":"JID of original message sender"},"IsForwarded":{"type":"boolean","example":true,"description":"Set to true to mark the message as forwarded. This is the preferred method for forwarding messages."},"MentionedJID":{"type":"array","items":{"type":"string"},"example":["5511999999999@s.whatsapp.net","5491155553934@s.whatsapp.net"],"description":"Array of JIDs to mention in the message. Use full WhatsApp JID format (number@s.whatsapp.net)."},"MentionAll":{"type":"boolean","example":true,"description":"Set to true to mention all group members"}}}}},"CallRejectRequest":{"type":"object","description":"Body of `POST /call/reject/send`.","required":["call_id","call_from","reject_type"],"properties":{"call_id":{"type":"string","description":"Call ID from the call offer webhook.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Caller JID exactly as received in the call offer webhook (`@s.whatsapp.net` or `@lid`).","example":"5511999999999@s.whatsapp.net"},"reject_type":{"type":"string","description":"Rejection label. Required on this route (no default); echoed in the response.","enum":["busy","declined","unavailable"],"example":"busy"},"message":{"type":"string","description":"Optional text sent to the caller after the rejection (best effort).","example":"I'm in a meeting right now, I'll call you back soon."}}},"GetLIDRequest":{"type":"object","description":"Phone number whose LID is requested.","required":["phone"],"properties":{"phone":{"type":"string","description":"Phone number with country code or phone JID. Must not be a LID.","example":"5511999999999"}}},"GetJIDFromLIDRequest":{"type":"object","description":"LID whose phone number is requested.","required":["lid"],"properties":{"lid":{"type":"string","description":"LID with the `@lid` suffix.","example":"123456789012345@lid"}}},"LIDMappingsResponse":{"description":"Success envelope of `GET /user/lid/mappings`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Mapping list.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"mappings":{"type":"array","nullable":true,"description":"Phone/LID pairs; `null` when none exist.","items":{"type":"object","description":"One mapping.","properties":{"lid":{"type":"string","description":"Contact LID.","example":"123456789012345@lid"},"phone":{"type":"string","description":"Contact phone JID.","example":"5511999999999@s.whatsapp.net"}}}},"count":{"type":"integer","description":"Number of mappings returned.","example":2},"message":{"type":"string","description":"`No LID mappings found` when the list is empty; omitted otherwise.","example":"No LID mappings found"}}}}}]},"StatusText":{"type":"object","description":"Text status to post.","required":["text"],"properties":{"text":{"type":"string","description":"Status text. WhatsApp limits it to about 650 characters; the gateway does not check the length.","example":"Store open until 10 PM today!"},"background_color":{"type":"string","description":"Background color as an ARGB unsigned decimal string. Ignored when it does not parse.","example":"4280391411"},"text_color":{"type":"string","description":"Text color as an ARGB unsigned decimal string. Ignored when it does not parse.","example":"4294967295"},"font":{"type":"integer","description":"Font index 0-10 (0 SYSTEM, 1 SYSTEM_TEXT, 2 FB_SCRIPT, 6 SYSTEM_BOLD, 7 MORNINGBREEZE_REGULAR, 8 CALISTOGA_REGULAR, 9 EXO2_EXTRABOLD, 10 COURIERPRIME_BOLD). Defaults to 0; out-of-range values are ignored.","minimum":0,"maximum":10,"example":8},"id":{"type":"string","description":"Custom message ID. Generated when omitted.","example":"3EB0C0FFEE0000000001"},"audience":{"type":"array","description":"Only these contacts see the status. Individual phone digits (a leading `+` and spaces are accepted), `@s.whatsapp.net` or `@lid` JIDs. Other entries (groups, channels, text) are ignored; an empty or entirely invalid list uses the status privacy setting. Omit to use the status privacy setting.","items":{"type":"string"},"example":["5511999999999","123456789012345@lid"]},"exclude_list":{"type":"array","description":"Contacts removed from the audience (same formats as `audience`). Invalid entries are ignored. If nothing would remain, the status falls back to the account's status privacy instead of failing.","items":{"type":"string"},"example":["5511888888888"]}}},"StatusImage":{"type":"object","description":"Image status to post.","required":["image"],"properties":{"image":{"type":"string","description":"Base64 data URL (`data:image/jpeg;base64,...`) or HTTP(S) URL of the image.","example":"https://example.com/media/weekly-offer.jpg"},"caption":{"type":"string","description":"Caption shown with the image.","example":"This week's offer"},"id":{"type":"string","description":"Custom message ID. Generated when omitted.","example":"3EB0C0FFEE0000000002"},"audience":{"type":"array","description":"Only these contacts see the status. Individual phone digits (a leading `+` and spaces are accepted), `@s.whatsapp.net` or `@lid` JIDs. Other entries are ignored; an empty or entirely invalid list uses the status privacy setting. Omit to use the status privacy setting.","items":{"type":"string"},"example":["5511999999999"]},"exclude_list":{"type":"array","description":"Contacts removed from the audience. Invalid entries are ignored. If nothing would remain, the status falls back to the account's status privacy instead of failing.","items":{"type":"string"},"example":["5511888888888"]}}},"StatusVideo":{"type":"object","description":"Video status to post.","required":["video"],"properties":{"video":{"type":"string","description":"Base64 data URL (`data:video/mp4;base64,...`) or HTTP(S) URL of an MP4 (H.264 video, AAC audio).","example":"https://example.com/media/product-demo.mp4"},"caption":{"type":"string","description":"Caption shown with the video.","example":"30-second product demo"},"id":{"type":"string","description":"Custom message ID. Generated when omitted.","example":"3EB0C0FFEE0000000003"},"audience":{"type":"array","description":"Only these contacts see the status. Individual phone digits (a leading `+` and spaces are accepted), `@s.whatsapp.net` or `@lid` JIDs. Other entries are ignored; an empty or entirely invalid list uses the status privacy setting. Omit to use the status privacy setting.","items":{"type":"string"},"example":["5511999999999"]},"exclude_list":{"type":"array","description":"Contacts removed from the audience. Invalid entries are ignored. If nothing would remain, the status falls back to the account's status privacy instead of failing.","items":{"type":"string"},"example":["5511888888888"]}}},"StatusAudio":{"type":"object","description":"Audio or voice note status to post.","required":["audio"],"properties":{"audio":{"type":"string","description":"Base64 data URL or HTTP(S) URL. Voice notes should be OGG/Opus; audio files accept MP3, M4A/AAC or OGG.","example":"data:audio/ogg;base64,T2dnUwACAAAAAAAAAAAAAAAAAAAAAMhHv8oBE09wdXNIZWFkAQE4AYC7AAAAAABPZ2dT"},"caption":{"type":"string","description":"Accepted for compatibility but not attached to the audio status.","example":"Listen to this"},"ptt":{"type":"boolean","default":true,"description":"`true` posts a voice note (MIME normalized to `audio/ogg; codecs=opus`), `false` posts an audio file.","example":true},"id":{"type":"string","description":"Custom message ID. Generated when omitted.","example":"3EB0C0FFEE0000000004"},"audience":{"type":"array","description":"Only these contacts see the status. Individual phone digits (a leading `+` and spaces are accepted), `@s.whatsapp.net` or `@lid` JIDs. Other entries are ignored; an empty or entirely invalid list uses the status privacy setting. Omit to use the status privacy setting.","items":{"type":"string"},"example":["5511999999999"]},"exclude_list":{"type":"array","description":"Contacts removed from the audience. Invalid entries are ignored. If nothing would remain, the status falls back to the account's status privacy instead of failing.","items":{"type":"string"},"example":["5511888888888"]}}},"ChangePushNameRequest":{"type":"object","description":"New push name.","required":["push_name"],"properties":{"push_name":{"type":"string","description":"Display name shown to people who have not saved your number. Cannot be empty.","minLength":1,"example":"Example Store"}}},"SetMyStatusRequest":{"type":"object","description":"New status (about) text.","properties":{"status":{"type":"string","description":"About text; WhatsApp accepts up to 139 characters. Empty clears the text.","maxLength":139,"example":"Available for support 9am-6pm"}}},"SetProfilePhoto":{"type":"object","description":"New profile photo.","required":["Image"],"properties":{"Image":{"type":"string","description":"JPEG image as a base64 data URL (`data:image/jpeg;base64,...`) or an `http(s)` URL to download.","example":"https://example.com/images/profile.jpg"}}},"BusinessProfileRequest":{"type":"object","description":"Business account to look up.","required":["phone"],"properties":{"phone":{"type":"string","description":"Phone number with country code or user JID.","example":"5511988888888"}}},"LinkedGroupsRequest":{"type":"object","description":"Community whose sub-groups are listed. A `community` query parameter overrides this field.","required":["community"],"properties":{"community":{"type":"string","description":"Community (parent group) JID. Leading and trailing spaces are trimmed.","example":"120363000000000033@g.us"}}},"LinkedGroupsResponse":{"description":"Success envelope of the linked-groups routes.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Sub-groups of the community.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"community":{"type":"string","description":"Normalized community JID.","example":"120363000000000033@g.us"},"linked_groups":{"type":"array","nullable":true,"description":"Sub-groups of the community; `null` when there are none.","items":{"type":"object","description":"One sub-group.","properties":{"jid":{"type":"string","description":"Sub-group JID.","example":"120363000000000034@g.us"},"name":{"type":"string","description":"Sub-group name.","example":"Company Announcements"},"is_default_sub":{"type":"boolean","description":"`true` for the community announcement group.","example":true}}}},"count":{"type":"integer","description":"Number of sub-groups.","example":2}}}}}]},"GroupRequestsRequest":{"type":"object","description":"Group or community whose pending join requests are listed.","required":["group"],"properties":{"group":{"type":"string","description":"Group or community JID.","example":"120363000000000011@g.us"}}},"GroupRequestsResponse":{"description":"Success envelope of `POST /community/requests`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Pending join requests.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"group":{"type":"string","description":"Normalized group JID.","example":"120363000000000011@g.us"},"pending_requests":{"type":"array","nullable":true,"description":"People waiting for approval; `null` when nobody is waiting.","items":{"type":"object","description":"One pending request.","properties":{"jid":{"type":"string","description":"JID of the requester (LID or phone JID).","example":"123456789012345@lid"}}}},"count":{"type":"integer","description":"Number of pending requests.","example":2}}}}}]},"CreateCommunityRequest":{"type":"object","description":"Name and optional groups of a new community.","required":["name"],"properties":{"name":{"type":"string","minLength":1,"description":"Community name.","example":"Acme Company"},"description":{"type":"string","description":"Echoed in the response only; it is not sent to WhatsApp.","example":"Official community of Acme employees"},"groups":{"type":"array","description":"Existing group JIDs to link after creation. Failures are skipped silently.","items":{"type":"string","description":"Group JID.","example":"120363000000000011@g.us"},"example":["120363000000000011@g.us","120363000000000012@g.us"]}}},"CreateCommunityResponse":{"description":"Success envelope of `POST /community/create`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Creation result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Community created successfully"},"community":{"type":"object","description":"The new community.","properties":{"jid":{"type":"string","description":"Community JID assigned by WhatsApp.","example":"120363000000000033@g.us"},"name":{"type":"string","description":"Name from the request.","example":"Acme Company"},"description":{"type":"string","description":"Description from the request (not applied on WhatsApp).","example":"Official community of Acme employees"},"linked_groups":{"type":"array","nullable":true,"description":"Groups actually linked; `null` when none.","items":{"type":"string","description":"Linked group JID.","example":"120363000000000011@g.us"},"example":["120363000000000011@g.us"]}}}}}}}]},"CommunityAnnouncementRequest":{"type":"object","description":"Target JID and announcement text.","required":["community","message"],"properties":{"community":{"type":"string","description":"Parent community JID (the text goes to its default announcement sub-group) or the announcement group JID itself (sent as-is).","example":"120363000000000034@g.us"},"message":{"type":"string","minLength":1,"description":"Announcement text.","example":"Office closed on Friday for maintenance."},"linked_groups":{"type":"array","description":"Accepted but ignored.","items":{"type":"string","description":"Group JID (ignored).","example":"120363000000000011@g.us"},"example":["120363000000000011@g.us"]},"background_color":{"type":"string","description":"Accepted but ignored.","example":"#128C7E"},"font":{"type":"integer","description":"Accepted but ignored.","example":0}}},"CommunityAnnouncementResponse":{"description":"Success envelope of `POST /community/announcement`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Send result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Announcement sent successfully"},"community":{"type":"string","description":"Normalized community JID from the request.","example":"120363000000000034@g.us"},"announcement_group":{"type":"string","description":"JID that actually received the message — the default announcement sub-group when `community` is a parent community, otherwise `community` itself (also when the sub-group lookup failed).","example":"120363000000000035@g.us"},"message_id":{"type":"string","description":"WhatsApp message ID of the text.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","format":"date-time","description":"Server timestamp of the send.","example":"2026-09-15T12:00:00Z"}}}}}]},"ResolveBusinessLinkRequest":{"type":"object","description":"Business message link to resolve.","required":["link"],"properties":{"link":{"type":"string","description":"WhatsApp business message link or its code (`https://wa.me/message/<code>`). Required (`400 missing link in payload`).","example":"https://wa.me/message/ABCDEFGHIJKLM1"}},"example":{"link":"https://wa.me/message/ABCDEFGHIJKLM1"}},"ContactQRRequest":{"type":"object","description":"Options for the own contact QR link. The body must be a JSON object (use `{}` for defaults).","properties":{"revoked":{"type":"boolean","description":"True revokes the current contact QR link and returns a new one; false (default) returns the current link.","default":false,"example":false},"phone":{"type":"string","description":"Accepted for backward compatibility but ignored: the route always returns the link of the connected account.","example":"5511999999999"}},"example":{"revoked":false}},"BotProfilesRequest":{"type":"object","description":"Bots to describe.","required":["bot_jids"],"properties":{"bot_jids":{"type":"array","description":"Bot JIDs from `GET /business/bots` (at least one). Each must parse as a JID; JIDs not in the bot list are ignored.","items":{"type":"string"},"minItems":1,"example":["867051314767696@bot"]}},"example":{"bot_jids":["867051314767696@bot"]}},"UserDevicesRequest":{"type":"object","description":"Accounts whose devices are listed.","required":["user_jids"],"properties":{"user_jids":{"type":"array","description":"Phone numbers with country code, phone JIDs or LIDs. At least one item.","minItems":1,"items":{"type":"string","description":"Phone number, phone JID or LID.","example":"5511999999999@s.whatsapp.net"},"example":["5511999999999@s.whatsapp.net","5511988888888"]}}},"DeviceInfo":{"type":"object","description":"One device of a queried account.","properties":{"user_jid":{"type":"string","description":"Account JID the device belongs to (`user@server`).","example":"5511999999999@s.whatsapp.net"},"device_jid":{"type":"string","description":"Device JID (`user:device@server`; slot 0 has no suffix).","example":"5511999999999:7@s.whatsapp.net"},"device_id":{"type":"integer","description":"Device slot number; 0 is the primary phone.","example":7},"platform":{"type":"string","description":"Label derived from `device_id` (see `POST /device/platform`), not the real client platform.","example":"DESKTOP"}}},"LinkedDevicesResponse":{"description":"Success envelope of `GET /device/linked`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Devices of the connected account.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"jid":{"type":"string","description":"JID of this session's device, as stored after pairing.","example":"5511999999999:12@s.whatsapp.net"},"linked_devices":{"type":"array","nullable":true,"description":"Other devices of the account; `null` when none were found.","items":{"type":"object","description":"One registered device.","properties":{"device_jid":{"type":"string","description":"Device JID.","example":"5511999999999:7@s.whatsapp.net"},"device_id":{"type":"integer","description":"Device slot number; 0 is the primary phone.","example":7},"platform":{"type":"string","description":"Label derived from `device_id`, not the real client platform.","example":"DESKTOP"},"is_current":{"type":"boolean","description":"`true` when the slot equals this session's device. Normally `false`, because the own device is not listed.","example":false}}}},"count":{"type":"integer","description":"Number of devices returned.","example":2}}}}}]},"DevicePlatformRequest":{"type":"object","description":"Device ID to translate.","properties":{"device_id":{"type":"integer","description":"Device slot number. Missing means 0.","minimum":0,"example":7}}},"DevicePlatformResponse":{"description":"Success envelope of `POST /device/platform`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Lookup result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"device_id":{"type":"integer","description":"Echo of the requested device ID.","example":7},"platform":{"type":"string","description":"Platform label for the ID.","enum":["UNKNOWN","CHROME","FIREFOX","IE","OPERA","SAFARI","EDGE","DESKTOP","IPAD","ANDROID_TABLET","OHANA","ALOHA","CATALINA","TCL_TV"],"example":"DESKTOP"}}}}}]},"SetPrivacySettingRequest":{"type":"object","description":"Privacy setting to change.","required":["setting","value"],"properties":{"setting":{"type":"string","description":"Setting name (case-insensitive).","enum":["group_add","last_seen","status","profile","read_receipts","online","call_add"],"example":"last_seen"},"value":{"type":"string","description":"New value (case-insensitive). WhatsApp may reject values a setting does not support.","enum":["all","contacts","contact_blacklist","none"],"example":"contacts"},"users":{"type":"array","description":"Validated as JIDs but not applied; exception lists are not supported by this endpoint.","items":{"type":"string","description":"Phone number or JID.","example":"5511977777777"},"example":["5511977777777"]}}},"PrivacySettingsResponse":{"description":"Success envelope of `GET /privacy/settings`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Cached privacy settings.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"privacy_settings":{"type":"object","description":"Setting values; empty strings when WhatsApp could not be queried.","properties":{"group_add":{"type":"string","description":"Who can add you to groups.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"last_seen":{"type":"string","description":"Who can see your last seen.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"status":{"type":"string","description":"Who can see your status updates.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"profile":{"type":"string","description":"Who can see your profile photo.","enum":["all","contacts","contact_blacklist","none",""],"example":"all"},"read_receipts":{"type":"string","description":"Whether read receipts are sent.","enum":["all","none",""],"example":"all"},"online":{"type":"string","description":"Who can see when you are online.","enum":["all","match_last_seen",""],"example":"match_last_seen"},"call_add":{"type":"string","description":"Who can call you.","enum":["all","known",""],"example":"all"}}}}}}}]},"DisappearingTimerRequest":{"type":"object","description":"Default timer for new chats.","required":["timer"],"properties":{"timer":{"type":"string","description":"Timer value (case-insensitive). `off` or `0` disables it.","enum":["24h","7d","90d","off","0"],"example":"7d"}}},"UpdateBlocklistRequest":{"type":"object","description":"Contacts to block or unblock.","required":["action","users"],"properties":{"action":{"type":"string","description":"Operation to apply (case-insensitive).","enum":["block","unblock"],"example":"block"},"users":{"type":"array","description":"Phone numbers with country code or JIDs. At least one item.","minItems":1,"items":{"type":"string","description":"Phone number or JID.","example":"5511977777777"},"example":["5511977777777","5511966666666@s.whatsapp.net"]}}},"BlocklistResponse":{"description":"Success envelope of `GET /privacy/blocklist`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Blocklist.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"blocked_contacts":{"type":"array","nullable":true,"description":"Blocked JIDs; `null` when nobody is blocked.","items":{"type":"string"},"example":["5511977777777@s.whatsapp.net"]},"count":{"type":"integer","description":"Number of blocked JIDs.","example":1}}}}}]},"StatusPrivacyResponse":{"description":"Success envelope of `GET /privacy/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Status privacy.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"status_privacy":{"type":"string","description":"Who can see your status updates; empty when WhatsApp could not be queried.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"description":{"type":"string","description":"Fixed explanatory text.","example":"Status privacy setting (all, contacts, contact_blacklist, or none)"}}}}}]},"CallRejectV1Request":{"type":"object","description":"Body of `POST /call/reject`.","required":["call_id","call_from"],"properties":{"call_id":{"type":"string","description":"Call ID from the call offer webhook.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Caller JID from the call offer webhook (`@s.whatsapp.net` or `@lid`).","example":"5511999999999@s.whatsapp.net"},"reject_type":{"type":"string","description":"Rejection label, echoed in the response. Defaults to `declined`.","enum":["busy","declined","unavailable"],"default":"declined","example":"declined"},"message":{"type":"string","description":"Optional text sent to the caller after the rejection.","example":"We can't take calls right now. Please send us a message and we'll reply shortly."}}},"CallRejectV1Response":{"description":"Success envelope of `POST /call/reject`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Rejection result.","properties":{"success":{"type":"boolean","description":"Always `true` when the rejection stanza was sent.","example":true},"call_id":{"type":"string","description":"Echo of the requested call ID.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Caller JID normalized by the gateway.","example":"5511999999999@s.whatsapp.net"},"reject_type":{"type":"string","description":"Rejection label used (the default `declined` when omitted).","enum":["busy","declined","unavailable"],"example":"declined"},"action":{"type":"string","description":"Always `rejected`.","enum":["rejected"],"example":"rejected"},"message_sent":{"type":"boolean","description":"`true` only when a follow-up `message` was requested and WhatsApp accepted it.","example":false}}}}}],"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reject_type":"declined","action":"rejected","message_sent":false},"success":true}},"CallAcceptV1Request":{"type":"object","description":"Body of `POST /call/accept` and `POST /call/preaccept`.","required":["call_id","call_from"],"properties":{"call_id":{"type":"string","description":"Call ID from the call offer webhook.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Caller JID from the call offer webhook (`@s.whatsapp.net` or `@lid`).","example":"5511999999999@s.whatsapp.net"}}},"CallTerminateRequest":{"type":"object","description":"Body of `POST /call/terminate`.","required":["call_id","call_from"],"properties":{"call_id":{"type":"string","description":"Call ID from the call webhook.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"JID of the other party of the call (`@s.whatsapp.net` or `@lid`).","example":"5511999999999@s.whatsapp.net"},"reason":{"type":"string","description":"Terminate reason forwarded to WhatsApp. Defaults to `hangup`.","default":"hangup","example":"hangup"}}},"CallEngineConfig":{"type":"object","description":"Body of `PUT /call/config`. Full replace; only `callProviderToken` is kept when omitted.","properties":{"callsEnabled":{"type":"boolean","description":"Runs the native calls engine for this instance after the next reconnect. Omitted means `false`.","example":true},"callInboundMode":{"type":"string","description":"How inbound calls are handled. Empty or omitted means `webhook`. `reject` keeps the engine off entirely. `bot`, `ivr` and `ai` are accepted, but the voice-agent is unavailable in this build and such calls are rejected.","enum":["manual","bot","ivr","ai","webhook","reject"],"default":"webhook","example":"webhook"},"callRecord":{"type":"boolean","description":"Automatically records every connected call and uploads it to S3. Omitted means `false`.","example":true},"callSttUrl":{"type":"string","description":"Speech-to-text endpoint for the voice-agent. Omitted clears it.","example":"https://stt.example.com/v1/transcribe"},"callLlmUrl":{"type":"string","description":"Language-model endpoint for the voice-agent. Omitted clears it.","example":"https://llm.example.com/v1/chat"},"callTtsUrl":{"type":"string","description":"Text-to-speech endpoint for the voice-agent. Omitted clears it.","example":"https://tts.example.com/v1/speak"},"callProviderToken":{"type":"string","writeOnly":true,"description":"Bearer token for the provider endpoints. Write-only (never returned); kept when omitted.","example":"sk-example-provider-token"},"callSystemPrompt":{"type":"string","description":"System prompt for the voice-agent conversation. Omitted clears it.","example":"You are the virtual receptionist of Example Store. Be brief and friendly."},"callGreeting":{"type":"string","description":"Greeting spoken when the voice-agent answers. Omitted clears it.","example":"Hello! Thanks for calling Example Store. How can I help you?"}}},"CallDialRequest":{"type":"object","description":"Body of `POST /call/dial` and its alias `POST /call/initiate`.","required":["phone"],"properties":{"phone":{"type":"string","description":"Callee. Digits with country code and no `+` (resolved to the LID first), a phone JID (`@s.whatsapp.net`) or a LID (`@lid`). Group JIDs are not accepted.","example":"5511988888888"},"video":{"type":"boolean","default":false,"description":"`true` places a video call (H.264); otherwise voice only.","example":false}}},"CallIdRequest":{"type":"object","description":"Body carrying only the engine call ID (`/call/answer`, `/call/hangup`, `/call/record/start`, `/call/record/stop`).","required":["callId"],"properties":{"callId":{"type":"string","description":"Engine call ID from `/call/dial`, `GET /call/status` or the call webhooks.","example":"call_17B3F2A1C9D04E8F"}}},"CallPlayRequest":{"type":"object","description":"Body of `POST /call/play`. Send `callId` plus one audio source.","required":["callId"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call.","example":"call_17B3F2A1C9D04E8F"},"audioUrl":{"type":"string","format":"uri","description":"Public URL of a WAV, Ogg/Opus or MP3 file (30 s download timeout, 64 MiB cap). Takes precedence over `audioBase64`.","example":"https://cdn.example.com/audio/welcome-message.mp3"},"audioBase64":{"type":"string","format":"byte","description":"Standard base64 of a WAV, Ogg/Opus or MP3 file, without a `data:` prefix. Used when `audioUrl` is empty.","example":"UklGRiQAAABXQVZFZm10IBAAAAABAAEAgD4AAAB9AAACABAAZGF0YQAAAAA="}}},"CallInfo":{"type":"object","description":"One live call tracked by the native calls engine.","properties":{"callId":{"type":"string","description":"Engine call ID.","example":"call_17B3F2A1C9D04E8F"},"peer":{"type":"string","description":"JID of the remote peer as tracked by the engine.","example":"123456789012345@lid"},"state":{"type":"string","description":"Current call phase.","enum":["idle","calling","ringing","connecting","active","ended","unknown"],"example":"active"},"direction":{"type":"string","description":"Who started the call.","enum":["inbound","outbound"],"example":"inbound"},"video":{"type":"boolean","description":"Whether the call carries video.","example":false},"recording":{"type":"boolean","description":"Whether a recording is currently running.","example":true},"startedAt":{"type":"string","format":"date-time","description":"When the engine started tracking the call.","example":"2026-09-15T14:21:08.412Z"}}},"CallStatusResponse":{"description":"Success envelope of `GET /call/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Live calls snapshot.","properties":{"calls":{"type":"array","description":"Live calls; empty when no call is in progress.","items":{"$ref":"#/components/schemas/CallInfo"}}}}}}],"example":{"code":200,"data":{"calls":[{"callId":"call_17B3F2A1C9D04E8F","peer":"123456789012345@lid","state":"active","direction":"inbound","video":false,"recording":true,"startedAt":"2026-09-15T14:21:08.412Z"}]},"success":true}},"CallGroupDialRequest":{"type":"object","description":"Body of `POST /call/group/dial`.","required":["targets"],"properties":{"targets":{"type":"array","minItems":2,"maxItems":31,"description":"People to ring (at least two). WhatsApp accepts at most 31 remote targets.","items":{"type":"string","description":"Phone number with country code, phone JID or LID.","example":"5511988888888"},"example":["5511988888888","123456789012345@lid"]},"video":{"type":"boolean","default":false,"description":"`true` offers H.264 video to every participant.","example":false},"groupJid":{"type":"string","description":"Optional group the call is bound to while only `targets` are rung.","example":"120363000000000011@g.us"}}},"CallGroupDialByIDRequest":{"type":"object","description":"Body of `POST /call/group/dial-by-id`.","required":["groupJid"],"properties":{"groupJid":{"type":"string","description":"WhatsApp group whose members are rung.","example":"120363000000000011@g.us"},"video":{"type":"boolean","default":false,"description":"`true` offers H.264 video.","example":false}}},"CallParticipantsAddRequest":{"type":"object","description":"Body of `POST /call/participants/add`.","required":["callId","targets"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call.","example":"call_5C1E9A7B3D2F4E60"},"targets":{"type":"array","minItems":1,"description":"People to invite; each is invited independently.","items":{"type":"string","description":"Phone number with country code, phone JID or LID.","example":"5511966666666"},"example":["5511966666666"]}}},"CallParticipantRingRequest":{"type":"object","description":"Body of `POST /call/participants/ring`. Values must be strings.","required":["callId","target"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live group call.","example":"call_5C1E9A7B3D2F4E60"},"target":{"type":"string","description":"Roster participant to ring again (phone number, phone JID or LID).","example":"5511977777777"}}},"CallLinkCreateRequest":{"type":"object","description":"Optional body of `POST /call/link/create`.","properties":{"video":{"type":"boolean","default":false,"description":"`true` creates a video link; otherwise a voice link.","example":true}}},"CallLinkInfo":{"type":"object","description":"A created WhatsApp call link.","properties":{"token":{"type":"string","description":"Call-link token.","example":"Xk3pQ9aB7cD2eF4g"},"url":{"type":"string","format":"uri","description":"Shareable link, `https://call.whatsapp.com/audio/<token>` or `/video/<token>`.","example":"https://call.whatsapp.com/video/Xk3pQ9aB7cD2eF4g"},"video":{"type":"boolean","description":"Whether it is a video link.","example":true}}},"CallLinkPreviewInfo":{"type":"object","description":"Call-link metadata read without joining.","properties":{"token":{"type":"string","description":"Normalized call-link token.","example":"Xk3pQ9aB7cD2eF4g"},"video":{"type":"boolean","description":"Whether the link is a video link.","example":true},"approvalRequired":{"type":"boolean","description":"Whether joiners wait in the waiting room for an admin.","example":true},"isAdmin":{"type":"boolean","description":"Whether this account is an admin of the link.","example":false},"creator":{"type":"string","description":"JID of the link creator. Omitted when not disclosed.","example":"123456789012345@lid"},"creatorPhone":{"type":"string","description":"Phone JID of the creator. Omitted when not disclosed.","example":"5511988888888@s.whatsapp.net"}}},"CallLinkJoinRequest":{"type":"object","description":"Body of `POST /call/link/join`.","required":["token"],"properties":{"token":{"type":"string","description":"Call-link token or full `https://call.whatsapp.com/audio|video/<token>` URL.","example":"Xk3pQ9aB7cD2eF4g"},"video":{"type":"boolean","default":false,"description":"`true` joins with video.","example":false}}},"CallWaitingRoomUserRequest":{"type":"object","description":"Body of `POST /call/waiting-room/admit` and `/call/waiting-room/deny`. Values must be strings.","required":["callId","user"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call-link call.","example":"call_8D4B2E6A1C9F3E70"},"user":{"type":"string","description":"JID of the waiting user, as listed by `GET /call/{call_id}/waiting-room`.","example":"123456789012345@lid"}}},"CallApprovalRequest":{"type":"object","description":"Body of `POST /call/waiting-room/approval`.","required":["callId"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call-link call.","example":"call_8D4B2E6A1C9F3E70"},"enabled":{"type":"boolean","default":true,"description":"`true` requires approval (waiting room on), `false` lets joiners in directly. Must be a JSON boolean.","example":true}}},"CallReactionRequest":{"type":"object","description":"Body of `POST /call/reaction`. Values must be strings.","required":["callId","emoji"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call.","example":"call_5C1E9A7B3D2F4E60"},"emoji":{"type":"string","minLength":1,"description":"Emoji to show to the participants.","example":"👍"}}},"CallHandRequest":{"type":"object","description":"Body of `POST /call/hand`.","required":["callId"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call.","example":"call_5C1E9A7B3D2F4E60"},"raised":{"type":"boolean","default":true,"description":"`true` raises the hand, `false` lowers it. Must be a JSON boolean.","example":true}}},"CallVideoToggleRequest":{"type":"object","description":"Body of `POST /call/video`.","required":["callId"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call.","example":"call_17B3F2A1C9D04E8F"},"enabled":{"type":"boolean","default":true,"description":"`true` requests the upgrade to video, `false` stops outbound video. Must be a JSON boolean.","example":true}}},"CallScreenShareRequest":{"type":"object","description":"Body of `POST /call/screenshare`.","required":["callId"],"properties":{"callId":{"type":"string","description":"Engine call ID of the live call.","example":"call_5C1E9A7B3D2F4E60"},"enabled":{"type":"boolean","default":true,"description":"`true` announces a screen share, `false` ends it. Must be a JSON boolean.","example":true}}},"CallGroupState":{"type":"object","description":"Roster of a live group call.","properties":{"callId":{"type":"string","description":"Engine call ID.","example":"call_5C1E9A7B3D2F4E60"},"transactionId":{"type":"integer","description":"WhatsApp roster transaction counter; higher values are newer.","example":4},"participants":{"type":"array","description":"Participants in the roster, including this account.","items":{"type":"object","description":"One roster entry.","properties":{"jid":{"type":"string","description":"Participant JID (usually a LID).","example":"123456789012345@lid"},"phone":{"type":"string","description":"Phone JID when WhatsApp provided it. Omitted otherwise.","example":"5511988888888@s.whatsapp.net"},"state":{"type":"string","description":"Raw WhatsApp roster state, for example `connected`, `outgoing`, `receipt` or `invited`.","example":"connected"}}}}}},"CallWaitingRoomState":{"type":"object","description":"Waiting-room state of a live call-link call.","properties":{"callId":{"type":"string","description":"Engine call ID.","example":"call_8D4B2E6A1C9F3E70"},"enabled":{"type":"boolean","description":"Whether approval is required to join.","example":true},"isAdmin":{"type":"boolean","description":"Whether this account can admit or deny users.","example":true},"inWaitingRoom":{"type":"boolean","description":"Whether this account itself is waiting to be admitted.","example":false},"transactionId":{"type":"integer","description":"WhatsApp waiting-room transaction counter; higher values are newer.","example":2},"users":{"type":"array","description":"Users waiting for admission.","items":{"type":"object","description":"One waiting user.","properties":{"jid":{"type":"string","description":"JID of the waiting user; pass it as `user` to admit or deny.","example":"123456789012346@lid"},"phone":{"type":"string","description":"Phone JID when WhatsApp provided it. Omitted otherwise.","example":"5511977777777@s.whatsapp.net"}}}}}},"ChatReplyRequest":{"type":"object","description":"Text reply that quotes a previous message.","required":["to","quoted_msg_id","content_type"],"properties":{"to":{"type":"string","description":"Chat of the reply and of the quoted message. Phone number, user JID or group JID.","example":"5511999999999@s.whatsapp.net"},"quoted_msg_id":{"type":"string","description":"ID of the message being quoted.","example":"3EB0F2A1C9D04E8F1234"},"quoted_from_me":{"type":"boolean","default":false,"description":"`true` when the quoted message was sent by this account.","example":false},"quoted_sender":{"type":"string","description":"Author JID of the quoted message (needed in groups). Defaults to `to` when omitted or unparsable.","example":"5511888888888@s.whatsapp.net"},"content_type":{"type":"string","description":"Only `text` is supported; `image`, `video`, `document` and `audio` return 400.","enum":["text","image","video","document","audio"],"example":"text"},"content":{"type":"string","description":"Reply text. Required when `content_type` is `text`.","example":"Perfect, confirmed for tomorrow at 10 AM."}},"example":{"to":"5511999999999@s.whatsapp.net","quoted_msg_id":"3EB0F2A1C9D04E8F1234","quoted_from_me":false,"content_type":"text","content":"Perfect, confirmed for tomorrow at 10 AM."}},"OrderStateResponse":{"type":"object","description":"Order state kept by the gateway for a received order.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"seller_card_state":{"type":"string","description":"Always `local_to_acting_device`: the official apps keep the card state only on the device that acted; this state is the gateway's own.","example":"local_to_acting_device"},"state":{"type":"object","description":"Stored order state.","properties":{"version":{"type":"integer","description":"Payload version.","example":1},"incoming_message_id":{"type":"string","description":"ID of the received order message.","example":"3EB0C767D26A1D6B8A9F"},"order_id":{"type":"string","description":"Order ID from the received `OrderMessage`.","example":"1976123456789012"},"buyer":{"type":"string","description":"Buyer chat JID.","example":"5511999999999@s.whatsapp.net"},"state":{"type":"string","description":"Order decision state.","enum":["received","accepted","rejected"],"example":"accepted"},"payment_status":{"type":"string","description":"Last declared payment status, empty when none.","enum":["","pending","captured","failed"],"example":"captured"},"order_status":{"type":"string","description":"Last declared order lifecycle status, empty when none.","example":"shipped"},"billing_message_id":{"type":"string","description":"Billing message that accepted the order, empty before an accept.","example":"3EB0B1C2D3E4F5A6B7C8"},"reference_id":{"type":"string","description":"`reference_id` of the accepting billing, empty before an accept.","example":"order-2026-0915-001"},"updated_at":{"type":"integer","description":"Unix time (seconds) of the last change.","example":1790000900},"history":{"type":"array","description":"Last 100 changes, oldest first.","items":{"type":"object","description":"One recorded change.","properties":{"at":{"type":"integer","description":"Unix time (seconds) of the change.","example":1790000300},"event":{"type":"string","description":"Change kind.","enum":["received","accepted","rejected","payment_status","order_status"],"example":"accepted"},"value":{"type":"string","description":"New payment/order status, or the order ID for `received`; omitted when empty.","example":"shipped"},"source":{"type":"string","description":"`api` (sent by this gateway) or `device` (received from WhatsApp or sent from the seller's phone).","enum":["api","device"],"example":"device"},"message_id":{"type":"string","description":"WhatsApp message that carried the change.","example":"3EB0B1C2D3E4F5A6B7C8"},"note":{"type":"string","description":"`out_of_order` (phone action outside the expected order, recorded anyway) or `backfilled` (order received before tracking started); omitted when empty.","enum":["out_of_order","backfilled"],"example":"out_of_order"}}}}}}}},"OrderDetailsResponse":{"type":"object","description":"Order resolved by ID and token.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"order":{"type":"object","description":"Order details returned by WhatsApp.","properties":{"id":{"type":"string","description":"Order ID.","example":"1976123456789012"},"created_at":{"type":"string","description":"Order creation time.","format":"date-time","example":"2026-09-15T11:30:00Z"},"catalog_id":{"type":"string","description":"Seller catalog ID, when present.","example":"7123456789012300"},"price":{"type":"object","description":"Order totals.","properties":{"subtotal":{"type":"integer","description":"Subtotal in thousandths of the currency.","example":6000000},"total":{"type":"integer","description":"Total in thousandths of the currency.","example":6000000},"currency":{"type":"string","description":"ISO-4217 currency.","example":"BRL"},"price_status":{"type":"string","description":"Price status reported by WhatsApp, when present.","example":"PROVIDED"}}},"products":{"type":"array","description":"Ordered products.","items":{"type":"object","properties":{"id":{"type":"string","description":"Catalog product ID.","example":"7123456789012345"},"image_id":{"type":"string","description":"Product image ID, when present.","example":"7123456789012346"},"image_url":{"type":"string","description":"Product image URL, when present.","example":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg"},"price":{"type":"integer","description":"Unit price in thousandths of the currency.","example":3000000},"currency":{"type":"string","description":"ISO-4217 currency.","example":"BRL"},"name":{"type":"string","description":"Product name.","example":"Wooden chair"},"quantity":{"type":"integer","description":"Quantity.","example":2},"variant_info":{"type":"object","description":"Variant properties, when present.","properties":{"properties":{"type":"string","description":"Serialized variant properties.","example":"Color: Natural"}}}}}}}}}},"BusinessCatalogSendRequest":{"type":"object","description":"Catalog link message.","required":["to","business_jid"],"properties":{"to":{"type":"string","description":"Recipient chat: phone number or JID (user, LID or group).","example":"5511999999999@s.whatsapp.net"},"business_jid":{"type":"string","description":"Catalog owner: phone number, non-device phone JID, or `@lid` with a stored phone mapping.","example":"5511988888888@s.whatsapp.net"},"caption":{"type":"string","description":"Optional text placed before the link, separated by a blank line.","example":"Check out our full catalog"}},"example":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","caption":"Check out our full catalog"}},"BusinessProductSendRequest":{"type":"object","description":"Single product card message.","required":["to","business_jid","product_id"],"properties":{"to":{"type":"string","description":"Recipient chat: phone number or JID.","example":"5511999999999@s.whatsapp.net"},"business_jid":{"type":"string","description":"Catalog owner (phone number or JID). A phone JID is replaced by the owner's LID when the mapping is known.","example":"5511988888888@s.whatsapp.net"},"product_id":{"type":"string","description":"Catalog product ID.","example":"7123456789012345"},"caption":{"type":"string","description":"ID-only mode: product description. With `snapshot`/`use_catalog`: card body (at most 1024 bytes).","example":"Our best seller"},"quoted_msg_id":{"type":"string","description":"Optional ID of a real outgoing message stored for this session and chat to quote. Unknown IDs are ignored and reported in `quoted_message_reason`.","example":"3EB0C767D26A1D6B8A9F"},"use_catalog":{"type":"boolean","description":"True loads title, description, price, retailer ID, URL and first image from the owner's catalog.","default":false,"example":false},"snapshot":{"type":"object","description":"Explicit product card fields. With `use_catalog: true`, only the fields sent here override the catalog values.","properties":{"title":{"type":"string","description":"Card title, required in explicit mode, at most 256 bytes.","example":"Wooden chair"},"description":{"type":"string","description":"Card description, at most 4096 bytes.","example":"Solid wood chair with natural finish."},"currency":{"type":"string","description":"ISO-4217 uppercase currency; required when a price is present.","example":"BRL"},"price_amount1000":{"type":"integer","description":"Price in integer thousandths of the currency (`3000000` = 3,000.00).","example":3000000},"retailer_id":{"type":"string","description":"Retailer ID, at most 256 bytes.","example":"CHAIR-001"},"url":{"type":"string","description":"Absolute HTTPS product URL, at most 2048 bytes.","example":"https://example.com/products/chair"},"image":{"type":"string","description":"JPEG/PNG as base64 or `data:image/jpeg|png;base64,` URI (up to 16 MiB and 40 megapixels). URLs are not fetched. Replaces the catalog image with `use_catalog`.","example":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="}}}},"example":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","product_id":"7123456789012345","caption":"Our best seller"}},"BusinessProductListSendRequest":{"type":"object","description":"Product list message with sections.","required":["to","business_jid","sections"],"properties":{"to":{"type":"string","description":"Recipient chat: phone number or JID.","example":"5511999999999@s.whatsapp.net"},"business_jid":{"type":"string","description":"Catalog owner JID (phone or LID).","example":"5511988888888@s.whatsapp.net"},"header":{"type":"string","description":"List title, at most 60 bytes. Defaults to the Portuguese label `Catálogo` when empty.","example":"Weekly offers"},"body":{"type":"string","description":"Optional list description, at most 1024 bytes.","example":"Select the items you want"},"footer":{"type":"string","description":"Optional footer, at most 60 bytes.","example":"Valid until Sunday"},"use_catalog":{"type":"boolean","description":"True adds a header thumbnail from a catalog product image.","default":false,"example":false},"header_product_id":{"type":"string","description":"Product whose image becomes the header thumbnail with `use_catalog`; must belong to `sections` (defaults to the first product).","example":"7123456789012346"},"sections":{"type":"array","description":"1-10 sections with at most 30 products in total; product IDs must be unique across sections. A title is required when there is more than one section.","minItems":1,"maxItems":10,"items":{"type":"object","properties":{"title":{"type":"string","description":"Section title, at most 24 bytes.","example":"Chairs"},"products":{"type":"array","description":"Products of the section (at least one).","items":{"type":"object","properties":{"product_id":{"type":"string","description":"Catalog product ID.","example":"7123456789012345"}}}}}},"example":[{"title":"Chairs","products":[{"product_id":"7123456789012345"},{"product_id":"7123456789012346"}]},{"title":"Tables","products":[{"product_id":"7123456789012347"}]}]}},"example":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","header":"Weekly offers","body":"Select the items you want","footer":"Valid until Sunday","sections":[{"title":"Chairs","products":[{"product_id":"7123456789012345"},{"product_id":"7123456789012346"}]}]}},"BusinessShopSendRequest":{"type":"object","description":"Shop link message.","required":["to","business_jid"],"properties":{"to":{"type":"string","description":"Recipient chat: phone number or JID.","example":"5511999999999@s.whatsapp.net"},"business_jid":{"type":"string","description":"Shop owner: phone number, non-device phone JID, or `@lid` with a stored phone mapping.","example":"5511988888888@s.whatsapp.net"},"caption":{"type":"string","description":"Text placed before the link, separated by a space. Defaults to the Portuguese label `Acesse nossa loja:` when empty.","example":"Visit our official shop:"}},"example":{"to":"5511999999999@s.whatsapp.net","business_jid":"5511988888888@s.whatsapp.net","caption":"Visit our official shop:"}},"main.BusinessManagementAppealRequest":{"type":"object","properties":{"reason":{"description":"Appeal reason, required, non-blank, at most 1024 bytes.","type":"string","example":"The product is a handmade wooden chair and complies with the commerce policies.","minLength":1,"maxLength":1024}},"required":["reason"],"x-validation-constraints":{"required":["reason"],"properties":{"reason":{"example":"The product is a handmade wooden chair and complies with the commerce policies.","minLength":1,"maxLength":1024}}}},"main.BusinessManagementCollectionRequest":{"type":"object","properties":{"name":{"description":"Collection name, required, 1-256 bytes (trimmed).","type":"string","example":"Chairs","minLength":1,"maxLength":256},"product_ids":{"description":"Own product IDs to include. The gateway accepts 0-100 unique IDs, but WhatsApp requires 1-100 (an empty list returns `502`).","type":"array","items":{"type":"string"},"example":["7123456789012345"],"maxItems":100,"uniqueItems":true}},"required":["name"],"x-validation-constraints":{"required":["name"],"properties":{"name":{"example":"Chairs","minLength":1,"maxLength":256},"product_ids":{"description":"Own product IDs to include. The gateway accepts 0-100 unique IDs, but WhatsApp requires 1-100 (an empty list returns `502`).","example":["7123456789012345"],"maxItems":100,"uniqueItems":true}}}},"main.BusinessManagementCollectionsRequest":{"type":"object","properties":{"collection_ids":{"description":"Collection IDs to delete, 1-100 unique, each 1-256 bytes.","type":"array","items":{"type":"string"},"example":["7123456789012350"],"minItems":1,"maxItems":100,"uniqueItems":true}},"required":["collection_ids"],"x-validation-constraints":{"required":["collection_ids"],"properties":{"collection_ids":{"example":["7123456789012350"],"minItems":1,"maxItems":100,"uniqueItems":true}}}},"main.BusinessManagementEligibilityRequest":{"type":"object","properties":{"features":{"description":"Features to check, 1-6 unique values.","type":"array","items":{"$ref":"#/components/schemas/types.BusinessFeature"},"example":["meta_verified","bb_pro"],"minItems":1,"maxItems":6}},"required":["features"],"x-validation-constraints":{"required":["features"],"properties":{"features":{"example":["meta_verified","bb_pro"],"minItems":1,"maxItems":6}}}},"main.BusinessManagementEnabledRequest":{"type":"object","properties":{"enabled":{"description":"Required. true enables the shopping cart; false disables it.","type":"boolean","example":true}},"required":["enabled"],"x-validation-constraints":{"required":["enabled"],"properties":{"enabled":{"example":true}}}},"main.BusinessManagementHiddenRequest":{"type":"object","properties":{"hidden":{"description":"Required. true hides the product from public catalog reads; false shows it.","type":"boolean","example":true}},"required":["hidden"],"x-validation-constraints":{"required":["hidden"],"properties":{"hidden":{"example":true}}}},"main.BusinessManagementIDsRequest":{"type":"object","properties":{"product_ids":{"description":"Product IDs, 1-100 unique, each 1-256 bytes.","type":"array","items":{"type":"string"},"example":["7123456789012345","7123456789012346"],"minItems":1,"maxItems":100,"uniqueItems":true}},"required":["product_ids"],"x-validation-constraints":{"required":["product_ids"],"properties":{"product_ids":{"example":["7123456789012345","7123456789012346"],"minItems":1,"maxItems":100,"uniqueItems":true}}}},"main.BusinessManagementImageRequest":{"type":"object","properties":{"image":{"description":"JPEG or PNG bytes as standard base64 without data URI prefix (1 byte to 16 MiB; cover photos up to 5 MiB).","type":"string","format":"byte","example":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="}},"required":["image"],"x-validation-constraints":{"required":["image"],"properties":{"image":{"example":"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="}}}},"main.BusinessManagementMovesRequest":{"type":"object","properties":{"moves":{"description":"Collection moves, 1-100, unique collection_id, zero-based indices below 100.","type":"array","items":{"$ref":"#/components/schemas/types.BusinessCollectionMove"},"example":[{"collection_id":"7123456789012352","from_index":1,"to_index":0}],"minItems":1,"maxItems":100}},"required":["moves"],"x-validation-constraints":{"required":["moves"],"properties":{"moves":{"example":[{"collection_id":"7123456789012352","from_index":1,"to_index":0}],"minItems":1,"maxItems":100}}}},"main.BusinessManagementProductRequest":{"type":"object","properties":{"height":{"description":"Height in pixels of product media returned in the response: 0 (default 100) or 1-1024.","type":"integer","example":100,"minimum":0,"maximum":1024},"product":{"allOf":[{"$ref":"#/components/schemas/types.BusinessProductInput"}],"description":"Complete product fields. On PUT every omitted field is removed from the product.","example":{"name":"Wooden chair","description":"Solid wood chair with natural finish.","url":"https://example.com/products/chair","retailer_id":"CHAIR-001","currency":"BRL","price":"3000000","sale_price":"2499900","is_hidden":false,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"compliance_info":{"country_code_origin":"BR"}}},"width":{"description":"Width in pixels of product media returned in the response: 0 (default 100) or 1-1024.","type":"integer","example":100,"minimum":0,"maximum":1024}},"required":["product"],"x-validation-constraints":{"required":["product"],"properties":{"product":{"description":"Complete product fields. On PUT every omitted field is removed from the product.","example":{"name":"Wooden chair","description":"Solid wood chair with natural finish.","url":"https://example.com/products/chair","retailer_id":"CHAIR-001","currency":"BRL","price":"3000000","sale_price":"2499900","is_hidden":false,"image_urls":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"compliance_info":{"country_code_origin":"BR"}}},"width":{"example":100,"minimum":0,"maximum":1024},"height":{"example":100,"minimum":0,"maximum":1024}}}},"main.NetworkRouteRequest":{"type":"object","properties":{"authKey":{"description":"AuthKey is a JIT, single-use Tailscale auth key. It is write-only and is never persisted, returned, or logged.","type":"string","x-writeonly":"true","example":"tskey-auth-REDACTED"},"exitNodeId":{"description":"ExitNodeID is the stable Tailscale node ID, not a mutable hostname or IP.","type":"string","example":"nExampleStableExitNode"},"failClosed":{"description":"FailClosed decides what happens while the route is not ready: `true` holds the traffic;\n`false` (also the value when the field is omitted) lets the session leave through the default egress. Not holding traffic is an explicit operator\nchoice with a cost (the peer sees the session coming from another IP), so it is never inferred.","type":"boolean","example":true},"idempotencyKey":{"description":"IdempotencyKey identifies exactly one desired version and must be reused only for an identical retry.","type":"string","example":"route-2026-08-15-0001"},"mode":{"description":"Mode only accepts \"mobile\". Direct egress is deliberately unsupported.","type":"string","enum":["mobile"],"example":"mobile"},"routeVersion":{"description":"RouteVersion is a positive, monotonically increasing fencing token.","type":"integer","minimum":1,"example":1},"tcpOnly":{"description":"TCPOnly must be true. Native Calls/UDP is disabled while this route is desired.","type":"boolean","example":true}}},"main.NewsletterTargetRequest":{"type":"object","properties":{"Code":{"description":"Channel invite code or `https://whatsapp.com/channel/<code>` link (max 2048 bytes) for follow-invite/unfollow-invite; aliases code, invite_code.","type":"string","example":"0029VaExampleInviteCode01"},"NewsletterJID":{"description":"Newsletter JID (`<digits>@newsletter`) for follow, unfollow, info, messages; aliases newsletter_jid, jid, NewsletterID.","type":"string","example":"120363000000000022@newsletter"},"before_id":{"description":"On /newsletter/messages, return posts older than this server message ID (string or integer); aliases before, Before.","type":"string","example":"120"},"limit":{"description":"Posts to return on /newsletter/messages (1-1000, default 25); aliases count, Count.","type":"integer","example":25},"newsletter_jid":{"description":"Snake-case alias of NewsletterJID; must be identical when both are sent.","type":"string","example":"120363000000000022@newsletter"}}},"main.PasskeyResponsePayload":{"type":"object","properties":{"id":{"description":"Credential ID from the WebAuthn assertion, sent as-is (required).","type":"string","example":"Y3JlZGVudGlhbC1pZC0wMDAx"},"rawId":{"description":"Raw credential ID, base64url without padding (required).","type":"string","example":"Y3JlZGVudGlhbC1pZC0wMDAx"},"response":{"description":"Authenticator assertion data; all values base64url without padding.","type":"object","properties":{"authenticatorData":{"description":"Authenticator data bytes, base64url without padding (required).","type":"string","example":"ZmljdGl0aW91cy1hdXRoZW50aWNhdG9yLWRhdGE"},"clientDataJSON":{"description":"Client data JSON bytes, base64url without padding (required).","type":"string","example":"eyJ0eXBlIjoid2ViYXV0aG4uZ2V0Iiwib3JpZ2luIjoiaHR0cHM6Ly93ZWIud2hhdHNhcHAuY29tIn0"},"signature":{"description":"Assertion signature bytes, base64url without padding (required).","type":"string","example":"ZmljdGl0aW91cy1zaWduYXR1cmUtYnl0ZXM"},"userHandle":{"description":"Optional user handle bytes, base64url without padding.","type":"string","example":"dXNlci1oYW5kbGUtMDAwMQ"}}},"type":{"description":"Credential type, normally public-key (required).","type":"string","example":"public-key"}}},"main.UserContactLinkResolveRequest":{"type":"object","properties":{"code":{"description":"Contact QR code or https://wa.me/qr/ URL, 1-2048 bytes, no whitespace (required).","type":"string","maxLength":2048,"minLength":1,"example":"https://wa.me/qr/ABCDEFGHIJKL12"}}},"main.UserUsernameResolveRequest":{"type":"object","properties":{"key":{"description":"Optional four-digit key required by some usernames.","type":"string","maxLength":4,"minLength":4,"example":"4821"},"username":{"description":"WhatsApp username, 3-35 chars, optional leading @, no whitespace (required).","type":"string","example":"examplestore"}}},"main.WebAccount":{"type":"object","properties":{"accountSignature":{"description":"Account signature issued at pairing, base64 (required).","type":"string","example":"FRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVA=="},"accountSignatureKey":{"description":"Public key that produced the account signature, base64 (required).","type":"string","example":"HyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4="},"details":{"description":"Serialized ADVDeviceIdentity details, base64 (required).","type":"string","example":"CwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6"},"deviceSignature":{"description":"Device signature, base64 (required).","type":"string","example":"KSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj9AQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2BhYmNkZWZnaA=="}}},"main.WebDeviceSnapshot":{"type":"object","properties":{"account":{"description":"ADVSignedDeviceIdentity issued by WhatsApp at pairing (required).","allOf":[{"$ref":"#/components/schemas/main.WebAccount"}]},"advSecretKey":{"description":"Optional ADV secret key, base64; a fresh random key is kept when omitted.","type":"string","example":"MzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVI="},"businessName":{"description":"Optional business name stored on the device.","type":"string","example":"Example Store"},"identityKey":{"description":"Signal identity key pair of the device (required).","allOf":[{"$ref":"#/components/schemas/main.WebKeyPair"}]},"lid":{"description":"Optional device LID JID, e.g. 123456789012345:12@lid.","type":"string","example":"123456789012345:12@lid"},"meJid":{"description":"Device JID of the imported session, e.g. 5511999999999:12@s.whatsapp.net (required).","type":"string","example":"5511999999999:12@s.whatsapp.net"},"noiseKey":{"description":"Noise protocol key pair of the device (required).","allOf":[{"$ref":"#/components/schemas/main.WebKeyPair"}]},"platform":{"description":"Optional platform label stored on the device.","type":"string","example":"chrome"},"pushName":{"description":"Optional push name stored on the device.","type":"string","example":"Support Line"},"registrationId":{"description":"Signal registration ID of the device; must be non-zero (required).","type":"integer","example":12345},"signedPreKey":{"description":"Signed pre-key with its identity-key signature (required).","allOf":[{"$ref":"#/components/schemas/main.WebSignedPreKey"}]}}},"main.WebKeyPair":{"type":"object","properties":{"priv":{"description":"Private key, 32 bytes, base64 (standard or URL alphabet, padded or not) (required).","type":"string","example":"AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="},"pub":{"description":"Optional public key, base64; ignored because it is derived from priv.","type":"string","example":"yVb3ZlK0exampleDerivedPublicKey0000000000="}}},"main.WebSignedPreKey":{"type":"object","properties":{"keyId":{"description":"Signed pre-key ID.","type":"integer","example":1},"priv":{"description":"Private key, 32 bytes, base64 (required).","type":"string","example":"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpbXF1eX2A="},"pub":{"description":"Optional public key, base64; ignored because it is derived from priv.","type":"string","example":"Zm9vYmFyZXhhbXBsZURlcml2ZWRQdWJsaWNLZXkwMA=="},"signature":{"description":"Signature of the public key by the identity key, 64 bytes, base64 (required).","type":"string","example":"YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH1+f4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foA=="}}},"types.BusinessAddress":{"type":"object","properties":{"city":{"type":"string","description":"City, at most 256 bytes.","example":"Springfield","maxLength":256},"country_code":{"type":"string","description":"ISO-3166 alpha-2 country code (at most 3 bytes).","example":"US","maxLength":3},"postal_code":{"type":"string","description":"Postal code, at most 64 bytes.","example":"62701","maxLength":64},"region":{"type":"string","description":"State or region, at most 256 bytes.","example":"IL","maxLength":256},"street1":{"type":"string","description":"Street line 1, at most 512 bytes.","example":"100 Example Street","maxLength":512},"street2":{"type":"string","description":"Street line 2, at most 512 bytes.","example":"Suite 200","maxLength":512}},"x-validation-constraints":{"properties":{"street1":{"description":"Street line 1, at most 512 bytes.","example":"100 Example Street","maxLength":512},"street2":{"description":"Street line 2, at most 512 bytes.","example":"Suite 200","maxLength":512},"city":{"description":"City, at most 256 bytes.","example":"Springfield","maxLength":256},"region":{"description":"State or region, at most 256 bytes.","example":"IL","maxLength":256},"postal_code":{"description":"Postal code, at most 64 bytes.","example":"62701","maxLength":64},"country_code":{"description":"ISO-3166 alpha-2 country code (at most 3 bytes).","example":"US","maxLength":3}}}},"types.BusinessCollectionMove":{"type":"object","properties":{"collection_id":{"type":"string","description":"Current collection ID, unique across moves, 1-256 bytes.","example":"7123456789012352","minLength":1,"maxLength":256},"from_index":{"type":"integer","description":"Current zero-based position (0-99).","example":1,"minimum":0,"maximum":99},"to_index":{"type":"integer","description":"Target zero-based position (0-99).","example":0,"minimum":0,"maximum":99}},"required":["collection_id","from_index","to_index"],"x-validation-constraints":{"required":["collection_id","from_index","to_index"],"properties":{"collection_id":{"description":"Current collection ID, unique across moves, 1-256 bytes.","example":"7123456789012352","minLength":1,"maxLength":256},"from_index":{"description":"Current zero-based position (0-99).","example":1,"minimum":0,"maximum":99},"to_index":{"description":"Target zero-based position (0-99).","example":0,"minimum":0,"maximum":99}}}},"types.BusinessCollectionUpdate":{"type":"object","properties":{"add_product_ids":{"type":"array","items":{"type":"string"},"description":"Own product IDs to add (0-100 unique, 1-256 bytes each). Must not repeat an ID from `remove_product_ids`.","example":["7123456789012346"],"maxItems":100,"uniqueItems":true},"name":{"type":"string","description":"New collection name, 1-256 bytes (trimmed). Omit to keep the current name.","example":"Dining chairs","minLength":1,"maxLength":256},"remove_product_ids":{"type":"array","items":{"type":"string"},"description":"Product IDs to remove from the collection (0-100 unique, 1-256 bytes each).","example":["7123456789012345"],"maxItems":100,"uniqueItems":true}},"x-validation-constraints":{"properties":{"name":{"description":"New collection name, 1-256 bytes (trimmed). Omit to keep the current name.","example":"Dining chairs","minLength":1,"maxLength":256},"add_product_ids":{"description":"Own product IDs to add (0-100 unique, 1-256 bytes each). Must not repeat an ID from `remove_product_ids`.","example":["7123456789012346"],"maxItems":100,"uniqueItems":true},"remove_product_ids":{"description":"Product IDs to remove from the collection (0-100 unique, 1-256 bytes each).","example":["7123456789012345"],"maxItems":100,"uniqueItems":true}}}},"types.BusinessComplianceInfo":{"type":"object","properties":{"country_code_origin":{"type":"string","description":"ISO-3166 alpha-2 country of origin (at most 3 bytes).","example":"BR","maxLength":3},"importer_address":{"allOf":[{"$ref":"#/components/schemas/types.BusinessAddress"}],"description":"Importer address, when the product is imported.","example":{"street1":"100 Example Street","city":"Springfield","region":"IL","postal_code":"62701","country_code":"US"}},"importer_name":{"type":"string","description":"Importer legal name, at most 256 bytes.","example":"Example Imports Ltd","maxLength":256}},"x-validation-constraints":{"properties":{"country_code_origin":{"description":"ISO-3166 alpha-2 country of origin (at most 3 bytes).","example":"BR","maxLength":3},"importer_name":{"description":"Importer legal name, at most 256 bytes.","example":"Example Imports Ltd","maxLength":256},"importer_address":{"description":"Importer address, when the product is imported.","example":{"street1":"100 Example Street","city":"Springfield","region":"IL","postal_code":"62701","country_code":"US"}}}}},"types.BusinessFeature":{"type":"string","enum":["meta_verified","marketing_messages","genai","genai_image","meta_one","bb_pro"],"x-enum-varnames":["BusinessFeatureMetaVerified","BusinessFeatureMarketingMessages","BusinessFeatureGenAI","BusinessFeatureGenAIImage","BusinessFeatureMetaOne","BusinessFeatureBBPro"],"description":"Business feature to check: `meta_verified`, `marketing_messages`, `genai`, `genai_image`, `meta_one` or `bb_pro`.","example":"meta_verified","x-validation-constraints":{"description":"Business feature to check: `meta_verified`, `marketing_messages`, `genai`, `genai_image`, `meta_one` or `bb_pro`.","example":"meta_verified"}},"types.BusinessHoursDay":{"type":"object","properties":{"closeTime":{"type":"integer","description":"Closing time in minutes after midnight (0-1439), different from openTime. Only with `specific_hours`.","example":1080,"minimum":0,"maximum":1439},"dayOfWeek":{"type":"string","description":"Day of the week.","enum":["sun","mon","tue","wed","thu","fri","sat"],"example":"mon"},"mode":{"type":"string","description":"`specific_hours` uses openTime/closeTime; `open_24h` and `appointment_only` must not send them.","enum":["specific_hours","open_24h","appointment_only"],"example":"specific_hours"},"openTime":{"type":"integer","description":"Opening time in minutes after midnight (0-1439). Only with `specific_hours`.","example":540,"minimum":0,"maximum":1439}},"x-validation-constraints":{"properties":{"dayOfWeek":{"description":"Day of the week.","enum":["sun","mon","tue","wed","thu","fri","sat"],"example":"mon"},"mode":{"description":"`specific_hours` uses openTime/closeTime; `open_24h` and `appointment_only` must not send them.","enum":["specific_hours","open_24h","appointment_only"],"example":"specific_hours"},"openTime":{"description":"Opening time in minutes after midnight (0-1439). Only with `specific_hours`.","example":540,"minimum":0,"maximum":1439},"closeTime":{"description":"Closing time in minutes after midnight (0-1439), different from openTime. Only with `specific_hours`.","example":1080,"minimum":0,"maximum":1439}}}},"types.BusinessHoursUpdate":{"type":"object","properties":{"days":{"type":"array","items":{"$ref":"#/components/schemas/types.BusinessHoursDay"},"description":"Up to 7 entries with unique `dayOfWeek`.","example":[{"dayOfWeek":"mon","mode":"specific_hours","openTime":540,"closeTime":1080}],"maxItems":7},"timeZone":{"type":"string","description":"IANA time zone of the schedule.","example":"America/Sao_Paulo"}},"x-validation-constraints":{"properties":{"timeZone":{"description":"IANA time zone of the schedule.","example":"America/Sao_Paulo"},"days":{"description":"Up to 7 entries with unique `dayOfWeek`.","example":[{"dayOfWeek":"mon","mode":"specific_hours","openTime":540,"closeTime":1080}],"maxItems":7}}}},"types.BusinessMerchantCompliance":{"type":"object","properties":{"customer_care_details":{"allOf":[{"$ref":"#/components/schemas/types.BusinessMerchantContact"}],"description":"Customer care contact shown to buyers. Omitted fields are sent as empty strings.","example":{"email":"support@example.com","landline_number":"","mobile_number":"5511999999999"}},"entity_name":{"type":"string","description":"Registered legal name, required, 1-256 bytes after trimming.","example":"Example Store Ltd","minLength":1,"maxLength":256},"entity_type":{"allOf":[{"$ref":"#/components/schemas/types.BusinessMerchantEntityType"}],"description":"Legal entity type. `OTHER` requires `entity_type_custom`.","example":"PRIVATE_COMPANY"},"entity_type_custom":{"type":"string","description":"Custom entity type, required when `entity_type` is `OTHER` (at most 256 bytes).","example":"Cooperative","maxLength":256},"grievance_officer_details":{"allOf":[{"$ref":"#/components/schemas/types.BusinessMerchantOfficer"}],"description":"Grievance officer contact. Omitted fields are sent as empty strings.","example":{"name":"Jane Doe","email":"compliance@example.com","landline_number":"","mobile_number":"5511988888888"}},"is_registered":{"type":"boolean","description":"Whether the business is formally registered.","example":true}},"required":["entity_name","entity_type"],"x-validation-constraints":{"required":["entity_name","entity_type"],"properties":{"entity_name":{"description":"Registered legal name, required, 1-256 bytes after trimming.","example":"Example Store Ltd","minLength":1,"maxLength":256},"entity_type":{"description":"Legal entity type. `OTHER` requires `entity_type_custom`.","example":"PRIVATE_COMPANY"},"entity_type_custom":{"description":"Custom entity type, required when `entity_type` is `OTHER` (at most 256 bytes).","example":"Cooperative","maxLength":256},"is_registered":{"description":"Whether the business is formally registered.","example":true},"customer_care_details":{"description":"Customer care contact shown to buyers. Omitted fields are sent as empty strings.","example":{"email":"support@example.com","landline_number":"","mobile_number":"5511999999999"}},"grievance_officer_details":{"description":"Grievance officer contact. Omitted fields are sent as empty strings.","example":{"name":"Jane Doe","email":"compliance@example.com","landline_number":"","mobile_number":"5511988888888"}}}}},"types.BusinessMerchantContact":{"type":"object","properties":{"email":{"type":"string","description":"Contact email, at most 254 bytes.","example":"support@example.com","maxLength":254},"landline_number":{"type":"string","description":"Landline number, at most 64 bytes. Empty string when not set.","example":"","maxLength":64},"mobile_number":{"type":"string","description":"Mobile number, at most 64 bytes.","example":"5511999999999","maxLength":64}},"x-validation-constraints":{"properties":{"email":{"description":"Contact email, at most 254 bytes.","example":"support@example.com","maxLength":254},"landline_number":{"description":"Landline number, at most 64 bytes. Empty string when not set.","example":"","maxLength":64},"mobile_number":{"description":"Mobile number, at most 64 bytes.","example":"5511999999999","maxLength":64}}}},"types.BusinessMerchantEntityType":{"type":"string","enum":["SOLE_PROPRIETORSHIP","PARTNERSHIP","PRIVATE_COMPANY","PUBLIC_COMPANY","LIMITED_LIABILITY_PARTNERSHIP","OTHER"],"x-enum-varnames":["BusinessMerchantEntitySoleProprietorship","BusinessMerchantEntityPartnership","BusinessMerchantEntityPrivateCompany","BusinessMerchantEntityPublicCompany","BusinessMerchantEntityLimitedLiabilityPartnership","BusinessMerchantEntityOther"],"description":"Legal entity type of the merchant.","example":"PRIVATE_COMPANY","x-validation-constraints":{"description":"Legal entity type of the merchant.","example":"PRIVATE_COMPANY"}},"types.BusinessMerchantOfficer":{"type":"object","properties":{"email":{"type":"string","description":"Officer email, at most 254 bytes.","example":"compliance@example.com","maxLength":254},"landline_number":{"type":"string","description":"Landline number, at most 64 bytes. Empty string when not set.","example":"","maxLength":64},"mobile_number":{"type":"string","description":"Mobile number, at most 64 bytes.","example":"5511988888888","maxLength":64},"name":{"type":"string","description":"Officer name, at most 256 bytes.","example":"Jane Doe","maxLength":256}},"x-validation-constraints":{"properties":{"name":{"description":"Officer name, at most 256 bytes.","example":"Jane Doe","maxLength":256},"email":{"description":"Officer email, at most 254 bytes.","example":"compliance@example.com","maxLength":254},"landline_number":{"description":"Landline number, at most 64 bytes. Empty string when not set.","example":"","maxLength":64},"mobile_number":{"description":"Mobile number, at most 64 bytes.","example":"5511988888888","maxLength":64}}}},"types.BusinessProductInput":{"type":"object","properties":{"compliance_category":{"type":"string","description":"Set `COUNTRY_ORIGIN_EXEMPT` (without `compliance_info`) when a country of origin does not apply. At most 128 bytes.","example":"COUNTRY_ORIGIN_EXEMPT","maxLength":128},"compliance_info":{"allOf":[{"$ref":"#/components/schemas/types.BusinessComplianceInfo"}],"description":"Country of origin and optional importer. Optional in the API; omitting it on PUT removes the country of origin.","example":{"country_code_origin":"BR","importer_name":"Example Imports Ltd"}},"currency":{"type":"string","description":"ISO-4217 uppercase code. Required with `price`; forbidden without it.","example":"BRL","minLength":3,"maxLength":3},"description":{"type":"string","description":"Product description, at most 4096 bytes.","example":"Solid wood chair with natural finish.","maxLength":4096},"image_urls":{"type":"array","items":{"type":"string"},"description":"1-10 HTTPS WhatsApp/Meta media URLs (`*.whatsapp.net`, `*.fbcdn.net`, `*.facebook.com`), normally the `image_id` returned by `POST /business/products/image`. The first one is the main photo.","example":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"minItems":1,"maxItems":10},"is_hidden":{"type":"boolean","description":"True creates or keeps the product hidden. Always sent on PUT, so omitting it makes the product visible.","example":false},"name":{"type":"string","description":"Product name, required, 1-256 bytes after trimming (`400 product name must contain 1-256 bytes`).","example":"Wooden chair","minLength":1,"maxLength":256},"price":{"type":"string","description":"Price as a string with integer thousandths of the currency, no separators (`\"3000000\"` = 3,000.00). Up to 18 digits.","example":"3000000"},"retailer_id":{"type":"string","description":"Seller SKU / retailer ID, at most 256 bytes.","example":"CHAIR-001","maxLength":256},"sale_price":{"type":"string","description":"Sale price in thousandths of the currency. Requires `price`; omitting it on PUT removes the sale price.","example":"2499900"},"url":{"type":"string","description":"Product page: absolute HTTPS URL, at most 2048 bytes.","example":"https://example.com/products/chair","maxLength":2048},"video_urls":{"type":"array","items":{"type":"string"},"description":"Up to 10 HTTPS WhatsApp/Meta media URLs of product videos.","example":["https://mmg.whatsapp.net/v/t42.1790-2/example-video.mp4"],"maxItems":10}},"required":["name","image_urls"],"x-validation-constraints":{"required":["name","image_urls"],"properties":{"name":{"description":"Product name, required, 1-256 bytes after trimming (`400 product name must contain 1-256 bytes`).","example":"Wooden chair","minLength":1,"maxLength":256},"description":{"description":"Product description, at most 4096 bytes.","example":"Solid wood chair with natural finish.","maxLength":4096},"currency":{"description":"ISO-4217 uppercase code. Required with `price`; forbidden without it.","example":"BRL","minLength":3,"maxLength":3},"price":{"description":"Price as a string with integer thousandths of the currency, no separators (`\"3000000\"` = 3,000.00). Up to 18 digits.","example":"3000000"},"sale_price":{"description":"Sale price in thousandths of the currency. Requires `price`; omitting it on PUT removes the sale price.","example":"2499900"},"url":{"description":"Product page: absolute HTTPS URL, at most 2048 bytes.","example":"https://example.com/products/chair","maxLength":2048},"retailer_id":{"description":"Seller SKU / retailer ID, at most 256 bytes.","example":"CHAIR-001","maxLength":256},"is_hidden":{"description":"True creates or keeps the product hidden. Always sent on PUT, so omitting it makes the product visible.","example":false},"image_urls":{"description":"1-10 HTTPS WhatsApp/Meta media URLs (`*.whatsapp.net`, `*.fbcdn.net`, `*.facebook.com`), normally the `image_id` returned by `POST /business/products/image`. The first one is the main photo.","example":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"],"minItems":1,"maxItems":10},"video_urls":{"description":"Up to 10 HTTPS WhatsApp/Meta media URLs of product videos.","example":["https://mmg.whatsapp.net/v/t42.1790-2/example-video.mp4"],"maxItems":10},"compliance_category":{"description":"Set `COUNTRY_ORIGIN_EXEMPT` (without `compliance_info`) when a country of origin does not apply. At most 128 bytes.","example":"COUNTRY_ORIGIN_EXEMPT","maxLength":128},"compliance_info":{"description":"Country of origin and optional importer. Optional in the API; omitting it on PUT removes the country of origin.","example":{"country_code_origin":"BR","importer_name":"Example Imports Ltd"}}}}},"types.BusinessProfileUpdate":{"type":"object","properties":{"address":{"type":"string","description":"Business address, at most 512 bytes. Omit or `null` to keep it unchanged.","example":"100 Example Street, Springfield, IL","maxLength":512},"description":{"type":"string","description":"Business description, at most 1024 bytes. Omit or `null` to keep it unchanged.","example":"Handmade wooden furniture.","maxLength":1024},"email":{"type":"string","description":"Contact email, at most 320 bytes, plain address only; an empty string clears it. Omit or `null` to keep it unchanged.","example":"contact@example.com","maxLength":320},"hours":{"allOf":[{"$ref":"#/components/schemas/types.BusinessHoursUpdate"}],"description":"Weekly business hours. Replaces the configured schedule when sent.","example":{"timeZone":"America/Sao_Paulo","days":[{"dayOfWeek":"mon","mode":"specific_hours","openTime":540,"closeTime":1080}]}},"websites":{"type":"array","items":{"type":"string"},"description":"Up to 2 absolute http/https URLs (at most 2048 bytes each); `[]` clears them. Omit or `null` to keep them unchanged.","example":["https://example.com"],"maxItems":2}},"x-validation-constraints":{"properties":{"address":{"description":"Business address, at most 512 bytes. Omit or `null` to keep it unchanged.","example":"100 Example Street, Springfield, IL","maxLength":512},"description":{"description":"Business description, at most 1024 bytes. Omit or `null` to keep it unchanged.","example":"Handmade wooden furniture.","maxLength":1024},"email":{"description":"Contact email, at most 320 bytes, plain address only; an empty string clears it. Omit or `null` to keep it unchanged.","example":"contact@example.com","maxLength":320},"websites":{"description":"Up to 2 absolute http/https URLs (at most 2048 bytes each); `[]` clears them. Omit or `null` to keep them unchanged.","example":["https://example.com"],"maxItems":2},"hours":{"description":"Weekly business hours. Replaces the configured schedule when sent.","example":{"timeZone":"America/Sao_Paulo","days":[{"dayOfWeek":"mon","mode":"specific_hours","openTime":540,"closeTime":1080}]}}}}},"main.BusinessOrderSendItem":{"type":"object","properties":{"currency":{"type":"string","description":"ISO-4217 uppercase currency; all lines must match with `create_order`.","example":"BRL"},"name":{"type":"string","description":"Product name (1-256 bytes with `create_order`).","example":"Wooden chair"},"price":{"type":"string","description":"Legacy free-form price text; ignored by `create_order`, which uses `price_amount1000`.","example":"3000.00"},"price_amount1000":{"type":"integer","description":"Unit price in integer thousandths of the currency, required and non-negative with `create_order`.","example":3000000},"product_id":{"type":"string","description":"Catalog product ID of the seller (1-256 bytes with `create_order`).","example":"7123456789012345"},"quantity":{"type":"integer","description":"Quantity (1-100 with `create_order`; at most 100 items in total).","example":1}},"x-validation-constraints":{"properties":{"product_id":{"description":"Catalog product ID of the seller (1-256 bytes with `create_order`).","example":"7123456789012345"},"name":{"description":"Product name (1-256 bytes with `create_order`).","example":"Wooden chair"},"quantity":{"description":"Quantity (1-100 with `create_order`; at most 100 items in total).","example":1},"price":{"description":"Legacy free-form price text; ignored by `create_order`, which uses `price_amount1000`.","example":"3000.00"},"currency":{"description":"ISO-4217 uppercase currency; all lines must match with `create_order`.","example":"BRL"},"price_amount1000":{"description":"Unit price in integer thousandths of the currency, required and non-negative with `create_order`.","example":3000000}}}},"main.BusinessOrderSendRequest":{"type":"object","properties":{"business_jid":{"description":"Seller business JID (phone@s.whatsapp.net); the order message is sent to this chat.","type":"string","example":"5511988888888@s.whatsapp.net"},"create_order":{"description":"Register a real catalog order before sending; a 502 with order_created=true must not be retried as a new order.","type":"boolean","example":true},"order_id":{"description":"Order ID: free-form in legacy mode, must be empty with create_order, required with resend_registered_order.","type":"string","example":"1976123456789012"},"order_items":{"description":"Order lines; required unless resend_registered_order. create_order needs 1-100 unique lines with price_amount1000 and one currency.","type":"array","items":{"$ref":"#/components/schemas/main.BusinessOrderSendItem"},"example":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"currency":"BRL","price_amount1000":3000000}]},"order_message":{"description":"Optional text shown in the order message.","type":"string","example":"Order for one wooden chair"},"order_token":{"description":"OrderToken is an authenticated recovery secret, accepted in JSON only and never logged.","type":"string","example":"AR6example0rderT0kenBase64=="},"resend_registered_order":{"description":"ResendRegisteredOrder queries an existing order and sends it once without creating another. Mutually exclusive with CreateOrder.","type":"boolean","example":false}},"required":["business_jid"],"x-validation-constraints":{"required":["business_jid"],"properties":{"business_jid":{"example":"5511988888888@s.whatsapp.net"},"order_items":{"example":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"currency":"BRL","price_amount1000":3000000}]},"order_message":{"example":"Order for one wooden chair"},"order_id":{"example":"1976123456789012"},"create_order":{"example":true},"resend_registered_order":{"example":false},"order_token":{"example":"AR6example0rderT0kenBase64=="}}}},"main.GroupHistoryShareModeRequest":{"type":"object","required":["groupjid","mode"],"properties":{"groupjid":{"description":"Group JID (@g.us, no device) to configure.","type":"string","example":"120363000000000011@g.us"},"mode":{"description":"Who may share recent history: admin_share (admins only) or all_member_share (all members).","type":"string","enum":["admin_share","all_member_share"],"example":"admin_share"}}},"whatsmeow.BusinessCreatedOrder":{"type":"object","properties":{"order_id":{"type":"string"},"price":{"type":"object","properties":{"currency":{"type":"string"},"price_status":{"type":"string"},"subtotal_amount":{"type":"string"},"total_amount":{"type":"string"}}},"token":{"type":"string"}}},"main.BusinessBillingSendRequest":{"type":"object","properties":{"billing":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingParams"}],"description":"Charge and accept only: explicit billing payload; forbidden in status and payment modes.","example":{"reference_id":"REF-0001","type":"physical-goods","currency":"BRL","total_amount":{"value":15000,"offset":100},"order":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"subtotal":{"value":15000,"offset":100}},"payment_settings":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}}]}},"billing_message_id":{"description":"Status and payment only: ID of the own billing message to quote.","type":"string","example":"3EB0C767D26A1D6B8A9F"},"body":{"description":"Optional message text, at most 4096 bytes.","type":"string","example":"Your order is ready for payment.","maxLength":4096},"id":{"description":"Optional custom WhatsApp message ID, at most 128 bytes.","type":"string","example":"3EB0C767D26A1D6B8A90","maxLength":128},"image":{"description":"Charge only: optional JPEG/PNG base64 or data URI turned into a JPEG header thumbnail; forbidden elsewhere.","type":"string","example":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="},"incoming_message_id":{"description":"Accept only: ID of the received order message stored by this instance; forbidden in other modes.","type":"string","example":"3EB0C767D26A1D6B8A9F"},"order_status":{"description":"Payment mode only: optional order lifecycle status to declare with the payment.","type":"string","example":"processing"},"payment_method":{"description":"Payment mode only: declared payment method, at most 64 bytes.","type":"string","example":"pix","maxLength":64},"payment_timestamp":{"description":"Payment mode only: positive payment timestamp; payment_method or payment_timestamp is required.","type":"integer","example":1757937600,"minimum":1},"reference_id":{"description":"Status and payment only: reference_id of the quoted billing.","type":"string","example":"REF-0001"},"status":{"description":"Order status (status mode) or payment status pending|captured|failed (payment mode).","type":"string","example":"shipped"},"to":{"description":"Required buyer JID, individual @s.whatsapp.net or @lid without device.","type":"string","example":"5511999999999@s.whatsapp.net"}},"required":["to"],"x-validation-constraints":{"required":["to"],"properties":{"to":{"example":"5511999999999@s.whatsapp.net"},"id":{"example":"3EB0C767D26A1D6B8A90","maxLength":128},"body":{"example":"Your order is ready for payment.","maxLength":4096},"image":{"example":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8/x8AAwMCAO+/p9sAAAAASUVORK5CYII="},"incoming_message_id":{"example":"3EB0C767D26A1D6B8A9F"},"billing_message_id":{"example":"3EB0C767D26A1D6B8A9F"},"reference_id":{"example":"REF-0001"},"status":{"example":"shipped"},"payment_method":{"example":"pix","maxLength":64},"payment_timestamp":{"example":1757937600,"minimum":1},"order_status":{"example":"processing"},"billing":{"description":"Charge and accept only: explicit billing payload; forbidden in status and payment modes.","example":{"reference_id":"REF-0001","type":"physical-goods","currency":"BRL","total_amount":{"value":15000,"offset":100},"order":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"subtotal":{"value":15000,"offset":100}},"payment_settings":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}}]}}}}},"whatsmeow.BusinessBillingAmount":{"type":"object","properties":{"offset":{"type":"integer","description":"Positive divisor for `value` (use 100 for cents, 1000 for thousandths).","example":100,"minimum":1},"value":{"type":"integer","description":"Non-negative integer numerator; the amount is `value / offset` (`15000/100` = 150.00).","example":15000,"minimum":0}},"required":["value","offset"],"x-validation-constraints":{"required":["value","offset"],"properties":{"value":{"description":"Non-negative integer numerator; the amount is `value / offset` (`15000/100` = 150.00).","example":15000,"minimum":0},"offset":{"description":"Positive divisor for `value` (use 100 for cents, 1000 for thousandths).","example":100,"minimum":1}}}},"whatsmeow.BusinessBillingCards":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether card payment is offered.","example":true}},"required":["enabled"],"description":"`enabled` must be present; false is valid. Does not execute a payment.","x-validation-constraints":{"required":["enabled"],"description":"`enabled` must be present; false is valid. Does not execute a payment.","properties":{"enabled":{"description":"Whether card payment is offered.","example":true}}}},"whatsmeow.BusinessBillingExternalPayment":{"type":"object","properties":{"payment_instruction":{"type":"string","maxLength":1024,"x-maxBytes":1024,"minLength":1,"description":"Non-empty instruction text, at most 1024 UTF-8 bytes.","example":"Pay at https://example.com/pay/REF-0001"},"type":{"type":"string","maxLength":64,"x-maxBytes":64,"minLength":1,"example":"payment_instruction","description":"Instruction type; the observed value is `payment_instruction` (other strings are not proven to render)."}},"required":["type","payment_instruction"],"x-validation-constraints":{"required":["type","payment_instruction"],"properties":{"type":{"maxLength":64,"x-maxBytes":64,"minLength":1,"example":"payment_instruction","description":"Instruction type; the observed value is `payment_instruction` (other strings are not proven to render)."},"payment_instruction":{"maxLength":1024,"x-maxBytes":1024,"minLength":1,"description":"Non-empty instruction text, at most 1024 UTF-8 bytes.","example":"Pay at https://example.com/pay/REF-0001"}}}},"whatsmeow.BusinessBillingItem":{"type":"object","properties":{"amount":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingAmount"}],"description":"Unit amount.","example":{"value":15000,"offset":100}},"isCustomItem":{"type":"boolean","description":"True for an item that is not in the catalog; requires `retailer_id` starting with `custom-item` and no `product_id`.","example":false},"isQuantitySet":{"type":"boolean","description":"Optional flag forwarded as-is in the billing payload.","example":true},"name":{"type":"string","description":"Item name, 1-256 bytes.","example":"Wooden chair","minLength":1,"maxLength":256},"product_id":{"type":"string","description":"Catalog product ID (at most 256 bytes). `product_id` or `retailer_id` is required.","example":"7123456789012345","maxLength":256},"quantity":{"type":"integer","description":"Quantity, 1-100.","example":1,"minimum":1,"maximum":100},"retailer_id":{"type":"string","description":"Retailer ID (at most 256 bytes); custom items must start with `custom-item`.","example":"CHAIR-001","maxLength":256}},"required":["name","quantity","amount"],"x-validation-constraints":{"required":["name","quantity","amount"],"properties":{"isCustomItem":{"description":"True for an item that is not in the catalog; requires `retailer_id` starting with `custom-item` and no `product_id`.","example":false},"isQuantitySet":{"description":"Optional flag forwarded as-is in the billing payload.","example":true},"product_id":{"description":"Catalog product ID (at most 256 bytes). `product_id` or `retailer_id` is required.","example":"7123456789012345","maxLength":256},"retailer_id":{"description":"Retailer ID (at most 256 bytes); custom items must start with `custom-item`.","example":"CHAIR-001","maxLength":256},"name":{"description":"Item name, 1-256 bytes.","example":"Wooden chair","minLength":1,"maxLength":256},"quantity":{"description":"Quantity, 1-100.","example":1,"minimum":1,"maximum":100},"amount":{"description":"Unit amount.","example":{"value":15000,"offset":100}}}}},"whatsmeow.BusinessBillingOrder":{"type":"object","properties":{"discount":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingAmount"}],"description":"Optional discount, not larger than the subtotal.","example":{"value":3000,"offset":100}},"items":{"type":"array","items":{"$ref":"#/components/schemas/whatsmeow.BusinessBillingItem"},"description":"1-100 items.","example":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"minItems":1,"maxItems":100},"order_type":{"type":"string","description":"Order type; must be `ORDER`.","enum":["ORDER"],"example":"ORDER"},"shipping":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingAmount"}],"description":"Optional shipping amount.","example":{"value":2000,"offset":100}},"status":{"type":"string","description":"Initial order status; must be `payment_requested`.","enum":["payment_requested"],"example":"payment_requested"},"subtotal":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingAmount"}],"description":"Must equal the sum of quantity × amount of all items.","example":{"value":15000,"offset":100}},"tax":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingAmount"}],"description":"Optional tax amount.","example":{"value":0,"offset":100}}},"required":["status","order_type","items","subtotal"],"x-validation-constraints":{"required":["status","order_type","items","subtotal"],"properties":{"status":{"description":"Initial order status; must be `payment_requested`.","enum":["payment_requested"],"example":"payment_requested"},"order_type":{"description":"Order type; must be `ORDER`.","enum":["ORDER"],"example":"ORDER"},"items":{"description":"1-100 items.","example":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"minItems":1,"maxItems":100},"subtotal":{"description":"Must equal the sum of quantity × amount of all items.","example":{"value":15000,"offset":100}},"discount":{"description":"Optional discount, not larger than the subtotal.","example":{"value":3000,"offset":100}},"shipping":{"description":"Optional shipping amount.","example":{"value":2000,"offset":100}},"tax":{"description":"Optional tax amount.","example":{"value":0,"offset":100}}}}},"whatsmeow.BusinessBillingPIX":{"type":"object","properties":{"flow_type":{"type":"string","maxLength":64,"x-maxBytes":64,"description":"Optional flow type, omitted when empty; at most 64 UTF-8 bytes.","example":"static"},"key":{"type":"string","maxLength":256,"x-maxBytes":256,"minLength":1,"description":"PIX key, required, non-empty after trimming, at most 256 UTF-8 bytes.","example":"payments@example.com"},"key_type":{"type":"string","maxLength":64,"x-maxBytes":64,"minLength":1,"description":"PIX key type such as `EMAIL`, `PHONE`, `CPF`, `CNPJ` or `EVP`; required, at most 64 UTF-8 bytes.","example":"EMAIL"},"merchant_name":{"type":"string","maxLength":256,"x-maxBytes":256,"minLength":1,"description":"Merchant name shown to the buyer, required, at most 256 UTF-8 bytes.","example":"Example Store"}},"required":["key","key_type","merchant_name"],"x-validation-constraints":{"required":["key","key_type","merchant_name"],"properties":{"key":{"maxLength":256,"x-maxBytes":256,"minLength":1,"description":"PIX key, required, non-empty after trimming, at most 256 UTF-8 bytes.","example":"payments@example.com"},"key_type":{"maxLength":64,"x-maxBytes":64,"minLength":1,"description":"PIX key type such as `EMAIL`, `PHONE`, `CPF`, `CNPJ` or `EVP`; required, at most 64 UTF-8 bytes.","example":"EMAIL"},"flow_type":{"maxLength":64,"x-maxBytes":64,"description":"Optional flow type, omitted when empty; at most 64 UTF-8 bytes.","example":"static"},"merchant_name":{"maxLength":256,"x-maxBytes":256,"minLength":1,"description":"Merchant name shown to the buyer, required, at most 256 UTF-8 bytes.","example":"Example Store"}}}},"whatsmeow.BusinessBillingParams":{"type":"object","properties":{"additional_note":{"type":"string","description":"Optional note, at most 4096 bytes.","example":"Delivery in 5 business days.","maxLength":4096},"currency":{"type":"string","description":"Three uppercase letters (ISO-4217).","example":"BRL","minLength":3,"maxLength":3},"external_payment_configurations":{"type":"array","items":{"$ref":"#/components/schemas/whatsmeow.BusinessBillingExternalPayment"},"maxItems":5,"description":"Up to 5 external payment instructions.","example":[{"type":"payment_instruction","payment_instruction":"Pay at https://example.com/pay/REF-0001"}]},"order":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingOrder"}],"description":"Order with items and totals.","example":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"subtotal":{"value":15000,"offset":100}}},"order_request_id":{"type":"string","description":"Must NOT be sent: on accept it is derived from the verified incoming order (`400` otherwise).","example":""},"payment_settings":{"type":"array","items":{"$ref":"#/components/schemas/whatsmeow.BusinessBillingPaymentSetting"},"maxItems":2,"description":"PIX and/or cards settings; no repeated types.","example":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}}]},"reference_id":{"type":"string","description":"Seller reference, 1-256 bytes. Reused later by status and payment declarations.","example":"REF-0001","minLength":1,"maxLength":256},"total_amount":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingAmount"}],"description":"Must equal subtotal − discount + shipping + tax.","example":{"value":15000,"offset":100}},"type":{"type":"string","description":"Billing type; must be `physical-goods`.","enum":["physical-goods"],"example":"physical-goods"}},"description":"Billing (review and pay) payload. At least one payment configuration across the two arrays; does not execute a payment.","required":["reference_id","type","currency","total_amount","order"],"anyOf":[{"required":["payment_settings"],"properties":{"payment_settings":{"minItems":1}}},{"required":["external_payment_configurations"],"properties":{"external_payment_configurations":{"minItems":1}}}],"x-validation-constraints":{"description":"Billing (review and pay) payload. At least one payment configuration across the two arrays; does not execute a payment.","required":["reference_id","type","currency","total_amount","order"],"anyOf":[{"required":["payment_settings"],"properties":{"payment_settings":{"minItems":1}}},{"required":["external_payment_configurations"],"properties":{"external_payment_configurations":{"minItems":1}}}],"properties":{"reference_id":{"description":"Seller reference, 1-256 bytes. Reused later by status and payment declarations.","example":"REF-0001","minLength":1,"maxLength":256},"order_request_id":{"description":"Must NOT be sent: on accept it is derived from the verified incoming order (`400` otherwise).","example":""},"type":{"description":"Billing type; must be `physical-goods`.","enum":["physical-goods"],"example":"physical-goods"},"currency":{"description":"Three uppercase letters (ISO-4217).","example":"BRL","minLength":3,"maxLength":3},"total_amount":{"description":"Must equal subtotal − discount + shipping + tax.","example":{"value":15000,"offset":100}},"order":{"description":"Order with items and totals.","example":{"status":"payment_requested","order_type":"ORDER","items":[{"product_id":"7123456789012345","name":"Wooden chair","quantity":1,"amount":{"value":15000,"offset":100}}],"subtotal":{"value":15000,"offset":100}}},"additional_note":{"description":"Optional note, at most 4096 bytes.","example":"Delivery in 5 business days.","maxLength":4096},"payment_settings":{"maxItems":2,"description":"PIX and/or cards settings; no repeated types.","example":[{"type":"pix_static_code","pix_static_code":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}}]},"external_payment_configurations":{"maxItems":5,"description":"Up to 5 external payment instructions.","example":[{"type":"payment_instruction","payment_instruction":"Pay at https://example.com/pay/REF-0001"}]}}}},"whatsmeow.BusinessBillingPaymentSetting":{"type":"object","properties":{"cards":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingCards"}],"description":"Card settings (type `cards` only).","example":{"enabled":true}},"pix_static_code":{"allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessBillingPIX"}],"description":"PIX static code settings (type `pix_static_code` only).","example":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}},"type":{"type":"string","enum":["pix_static_code","cards"],"description":"`pix_static_code` requires `pix_static_code`; `cards` requires `cards`. Each type at most once.","example":"pix_static_code"}},"required":["type"],"oneOf":[{"required":["pix_static_code"],"properties":{"type":{"enum":["pix_static_code"]}},"not":{"required":["cards"],"properties":{"cards":{"type":"object"}}}},{"required":["cards"],"properties":{"type":{"enum":["cards"]}},"not":{"required":["pix_static_code"],"properties":{"pix_static_code":{"type":"object"}}}}],"x-validation-constraints":{"required":["type"],"properties":{"type":{"enum":["pix_static_code","cards"],"description":"`pix_static_code` requires `pix_static_code`; `cards` requires `cards`. Each type at most once.","example":"pix_static_code"},"pix_static_code":{"description":"PIX static code settings (type `pix_static_code` only).","example":{"key":"payments@example.com","key_type":"EMAIL","merchant_name":"Example Store"}},"cards":{"description":"Card settings (type `cards` only).","example":{"enabled":true}}},"oneOf":[{"required":["pix_static_code"],"properties":{"type":{"enum":["pix_static_code"]}},"not":{"required":["cards"],"properties":{"cards":{"type":"object"}}}},{"required":["cards"],"properties":{"type":{"enum":["cards"]}},"not":{"required":["pix_static_code"],"properties":{"pix_static_code":{"type":"object"}}}}]}},"main.BusinessOrderRejectRequest":{"type":"object","properties":{"body":{"description":"Optional note appended after the refusal text, at most 4096 bytes.","type":"string","example":"Item out of stock.","maxLength":4096},"id":{"description":"Optional custom WhatsApp message ID, at most 128 bytes.","type":"string","example":"3EB0C767D26A1D6B8A90","maxLength":128},"incoming_message_id":{"description":"Required ID of the received order message stored by this instance (max 128 bytes).","type":"string","example":"3EB0C767D26A1D6B8A9F","minLength":1,"maxLength":128},"to":{"description":"Required buyer JID, individual @s.whatsapp.net or @lid without device.","type":"string","example":"5511999999999@s.whatsapp.net"}},"required":["to","incoming_message_id"],"x-validation-constraints":{"required":["to","incoming_message_id"],"properties":{"to":{"example":"5511999999999@s.whatsapp.net"},"incoming_message_id":{"example":"3EB0C767D26A1D6B8A9F","minLength":1,"maxLength":128},"id":{"example":"3EB0C767D26A1D6B8A90","maxLength":128},"body":{"example":"Item out of stock.","maxLength":4096}}}},"main.GroupHistorySendRequest":{"type":"object","required":["bundle_id","group_jid","message_ids","notice_id","recipients"],"properties":{"bundle_id":{"description":"Unused message ID for the history bundle (max 128 chars, differs from notice_id, never reusable).","type":"string","maxLength":128,"example":"3EB0C767D26A1D6B8AA0"},"group_jid":{"description":"Group JID (@g.us, no device) whose retained messages are shared.","type":"string","example":"120363000000000011@g.us"},"message_ids":{"description":"1-100 distinct IDs (max 128 chars) of original messages retained for this user and group.","type":"array","items":{"type":"string"},"example":["3EB0C767D26A1D6B8A9F","3EB0C767D26A1D6B8A9E"]},"notice_id":{"description":"Unused message ID for the history notice (max 128 chars, differs from bundle_id, never reusable).","type":"string","maxLength":128,"example":"3EB0C767D26A1D6B8AA1"},"recipients":{"description":"1-100 distinct other current members: phone, @s.whatsapp.net or @lid JID without device.","type":"array","items":{"type":"string"},"example":["5511999999999","123456789012345@lid"]}}},"ChatFavoriteRequest":{"type":"object","description":"Adds one chat to, or removes it from, the Favorites list.","required":["phone","favorite"],"properties":{"phone":{"type":"string","description":"Chat to change. Phone number with country code (no `+`), user JID (`@s.whatsapp.net` or `@lid`) or group JID (`@g.us`).","example":"5511999999999"},"favorite":{"type":"boolean","description":"`true` adds the chat to Favorites, `false` removes it.","example":true},"force":{"type":"boolean","default":false,"description":"Only with `favorite=true`. When the current list is unknown, replace it with only this chat instead of failing with 409.","example":false}}},"ChatFavoriteResponse":{"description":"Success envelope of `POST /chat/favorite`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the Favorites update.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the update.","example":true},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"index_jid":{"type":"string","description":"JID written to the sync action (the LID when the mapping is known).","example":"123456789012345@lid"},"favorite":{"type":"boolean","description":"Echo of the requested `favorite` value.","example":true},"favorites":{"type":"array","description":"Complete ordered Favorites list after the change.","items":{"type":"string"},"example":["120363000000000011@g.us","123456789012345@lid"]}}}}}]},"ChatFavoritesListResponse":{"description":"Success envelope of `GET /chat/favorites`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Favorites list as known by the gateway.","properties":{"favorites":{"type":"array","description":"Ordered chat JIDs in Favorites. Empty while `known` is false.","items":{"type":"string"},"example":["123456789012345@lid","120363000000000011@g.us"]},"known":{"type":"boolean","description":"`true` once the list was observed from app state or sent through this API.","example":true},"complete":{"type":"boolean","description":"`true` only after a successful full sync (`refresh=true`).","example":true},"source":{"type":"string","description":"Where the list came from. Empty while `known` is false.","enum":["app_state","api",""],"example":"app_state"},"synced_at":{"type":"string","format":"date-time","description":"UTC time of the last successful full sync. Omitted when no full sync has succeeded.","example":"2026-09-15T01:40:00Z"}}}}}]},"ChatFavoritesReplaceRequest":{"type":"object","description":"Complete ordered Favorites list to write.","required":["phones"],"properties":{"phones":{"type":"array","description":"Complete ordered list of chats (phone numbers, user JIDs or group JIDs). An empty array clears Favorites.","items":{"type":"string","description":"Phone number with country code, user JID or group JID.","example":"5511999999999"},"example":["5511999999999","120363000000000011@g.us"]}}},"ChatFavoritesReplaceResponse":{"description":"Success envelope of `PUT /chat/favorites`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the Favorites replacement.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the update.","example":true},"favorites":{"type":"array","description":"Ordered list exactly as written to the sync action (LIDs when known).","items":{"type":"string"},"example":["123456789012345@lid","120363000000000011@g.us"]}}}}}]},"SessionS3ConfigRequest":{"type":"object","description":"Complete S3 storage configuration of the instance. The call is a full replace; omitted fields are stored empty, false or 0.","properties":{"enabled":{"type":"boolean","description":"Enables media uploads to this bucket. Omitted is stored as `false`.","example":true},"endpoint":{"type":"string","description":"S3 API endpoint URL. Leave empty for AWS S3; required for MinIO, B2, R2 and other providers.","example":"https://minio.example.com"},"region":{"type":"string","description":"Bucket region.","example":"us-east-1"},"bucket":{"type":"string","description":"Bucket that receives the media objects.","example":"whatsapp-media"},"access_key":{"type":"string","description":"Access key ID. Stored as sent and never returned by `GET /session/s3/config`.","example":"minio-access-example"},"secret_key":{"type":"string","description":"Secret access key. Stored as sent and never returned.","example":"minio-secret-example"},"path_style":{"type":"boolean","description":"Use path-style addressing (`endpoint/bucket/key`). Required by MinIO and most self-hosted providers.","example":true},"public_url":{"type":"string","description":"Optional base URL (for example a CDN) used to build the media links placed in events.","example":"https://cdn.example.com"},"media_delivery":{"type":"string","description":"How media appears in events: `base64` inline, `s3` link (`url` is an alias stored as `s3`), or `both`. Empty or omitted is stored as `base64`.","enum":["base64","s3","url","both"],"example":"both"},"retention_days":{"type":"integer","description":"Days to keep uploaded objects. `0` means no expiration.","minimum":0,"example":30},"disable_acl":{"type":"boolean","description":"Skip object ACLs on upload. Set to `true` for AWS buckets with \"Bucket owner enforced\" object ownership.","example":false}}},"SessionS3ConfigView":{"type":"object","description":"Stored S3 configuration as returned by `GET /session/s3/config`. The secret key is omitted.","properties":{"enabled":{"type":"boolean","description":"Whether media uploads to S3 are enabled.","example":true},"endpoint":{"type":"string","description":"S3 API endpoint URL; empty for AWS S3.","example":"https://minio.example.com"},"region":{"type":"string","description":"Bucket region.","example":"us-east-1"},"bucket":{"type":"string","description":"Bucket that receives the media objects.","example":"whatsapp-media"},"access_key":{"type":"string","description":"Always `***` (masked), even when no key is stored.","example":"***"},"path_style":{"type":"boolean","description":"Whether path-style addressing is used.","example":true},"public_url":{"type":"string","description":"Base URL used to build media links; empty when not set.","example":"https://cdn.example.com"},"media_delivery":{"type":"string","description":"Stored delivery mode. `url` is stored and returned as `s3`.","enum":["base64","s3","both"],"example":"s3"},"retention_days":{"type":"integer","description":"Days to keep uploaded objects; `0` means no expiration.","example":30},"disable_acl":{"type":"boolean","description":"Whether object ACLs are skipped on upload.","example":false}}},"SessionS3ConfigSaveResponse":{"description":"Success envelope of `POST /session/s3/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Save confirmation.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"S3 configuration saved successfully"},"Enabled":{"type":"boolean","description":"Echo of the saved `enabled` value.","example":true}}}}}]},"SessionS3ConfigGetResponse":{"description":"Success envelope of `GET /session/s3/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SessionS3ConfigView"}}}]},"SessionS3ConfigDeleteResponse":{"description":"Success envelope of `DELETE /session/s3/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Delete confirmation.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"S3 configuration deleted successfully"}}}}}]},"SessionS3TestResponse":{"description":"Success envelope of `POST /session/s3/test`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the bucket access test.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"S3 connection test successful"},"Bucket":{"type":"string","description":"Bucket that was listed.","example":"whatsapp-media"},"Region":{"type":"string","description":"Region of the tested configuration.","example":"us-east-1"}}}}}]},"SessionRabbitMQConfigRequest":{"type":"object","description":"Complete RabbitMQ publisher configuration of the instance. The call is a full replace; omitted fields are stored as false, empty or NULL.","properties":{"enabled":{"type":"boolean","description":"Enables event publishing to RabbitMQ. Omitted is stored as `false`.","example":true},"url":{"type":"string","description":"AMQP connection URL (`amqp://` or `amqps://`, with credentials and optional vhost).","example":"amqps://zzg_user:zzg_pass@rabbitmq.example.com:5671/whatsapp"},"exchange":{"type":"string","description":"Exchange that receives the events. O exchange e a fila padrão derivam do ID da instância; consulte `GET /session/rabbitmq/config`.","example":"whatsapp.events"},"exchange_type":{"type":"string","description":"Exchange type. Defaults to `topic` when empty and `enabled` is true; validated only when enabled.","enum":["topic","direct","fanout","headers"],"example":"topic"},"queue":{"type":"string","description":"Queue name. Supports `{user_id}` and `{event_type}` placeholders; with `{event_type}` one queue per event type is declared. O exchange e a fila padrão derivam do ID da instância; consulte `GET /session/rabbitmq/config`.","example":"user_{user_id}_event_{event_type}"},"queue_type":{"type":"string","description":"Queue type. Defaults to `classic` when empty and `enabled` is true; validated only when enabled.","enum":["classic","quorum","stream"],"example":"quorum"},"routing_key":{"type":"string","description":"Routing key. Supports `{user_id}` and `{event_type}` placeholders. Defaults to `events.#` when empty and enabled.","example":"whatsapp.{user_id}.{event_type}"},"events":{"type":"string","description":"Comma-separated canonical event names (case-sensitive) or `All`, for example `Message,ReadReceipt,Connected`. Spaces around names are trimmed. Empty means no events.","example":"Message,ReadReceipt,Connected"},"durable":{"type":"boolean","description":"Declare the exchange and queues as durable.","example":true},"auto_delete":{"type":"boolean","description":"Declare the exchange and queues with auto-delete.","example":false},"exclusive":{"type":"boolean","description":"Declare queues as exclusive to the publishing connection.","example":false},"no_wait":{"type":"boolean","description":"Declare exchange and queues without waiting for broker confirmation.","example":false},"delivery_mode":{"type":"integer","description":"AMQP delivery mode, `1` transient or `2` persistent. `0` or omitted is stored as `2`.","enum":[1,2],"example":2},"dead_letter_exchange":{"type":"string","description":"Dead-letter exchange for rejected or expired messages (`x-dead-letter-exchange`).","example":"dlx.zigzapy"},"dead_letter_routing_key":{"type":"string","description":"Routing key used when dead-lettering (`x-dead-letter-routing-key`).","example":"dlq.events"},"message_ttl":{"type":"integer","format":"int64","description":"Message TTL in milliseconds (`x-message-ttl`).","example":86400000},"max_length":{"type":"integer","format":"int64","description":"Maximum number of messages per queue (`x-max-length`).","example":100000},"max_length_bytes":{"type":"integer","format":"int64","description":"Maximum queue size in bytes (`x-max-length-bytes`).","example":104857600},"queue_arguments":{"type":"string","description":"Extra queue arguments as a JSON-encoded string. A JSON object here fails with `400 could not decode payload`.","example":"{\"x-overflow\":\"reject-publish\"}"},"exchange_arguments":{"type":"string","description":"Extra exchange arguments as a JSON-encoded string. A JSON object here fails with `400 could not decode payload`.","example":"{}"},"connection_pool_size":{"type":"integer","description":"Publisher connection pool size. Must be greater than 0; omitted uses the server default.","minimum":1,"example":50},"worker_count":{"type":"integer","description":"Concurrent publisher workers. Must be greater than 0; omitted uses the server default.","minimum":1,"example":50},"queue_buffer_size":{"type":"integer","description":"In-memory event buffer size before publishing. Must be greater than 0; omitted uses the server default.","minimum":1,"example":100000},"batch_size":{"type":"integer","description":"Events published per batch. Must be greater than 0; omitted uses the server default.","minimum":1,"example":500},"batch_timeout_ms":{"type":"integer","description":"Maximum wait in milliseconds before publishing a partial batch. Must be non-negative.","minimum":0,"example":100},"publish_timeout_ms":{"type":"integer","description":"Timeout in milliseconds for a single publish. Must be greater than 0.","minimum":1,"example":5000},"max_retries":{"type":"integer","description":"Retry attempts for a failed publish. Must be non-negative.","minimum":0,"example":3},"retry_delay_ms":{"type":"integer","description":"Delay in milliseconds between publish retries. Must be non-negative.","minimum":0,"example":1000}}},"SessionRabbitMQConfigView":{"type":"object","description":"Stored RabbitMQ configuration as returned by `GET /session/rabbitmq/config`. Optional fields appear only when a value is stored.","properties":{"enabled":{"type":"boolean","description":"Whether event publishing is enabled.","example":true},"url":{"type":"string","description":"Connection URL with the password replaced by `***`.","example":"amqps://zzg_user:***@rabbitmq.example.com:5671/whatsapp"},"exchange":{"type":"string","description":"Exchange name.","example":"whatsapp.events"},"exchange_type":{"type":"string","description":"Exchange type; empty when never enabled.","example":"topic"},"queue":{"type":"string","description":"Queue name or pattern.","example":"user_{user_id}_event_{event_type}"},"queue_type":{"type":"string","description":"Queue type; empty when never enabled.","example":"quorum"},"routing_key":{"type":"string","description":"Routing key or pattern.","example":"whatsapp.{user_id}.{event_type}"},"events":{"type":"string","description":"Comma-separated subscribed events.","example":"Message,ReadReceipt,Connected"},"durable":{"type":"boolean","description":"Durable declaration flag.","example":true},"auto_delete":{"type":"boolean","description":"Auto-delete declaration flag.","example":false},"exclusive":{"type":"boolean","description":"Exclusive queue flag.","example":false},"no_wait":{"type":"boolean","description":"No-wait declaration flag.","example":false},"delivery_mode":{"type":"integer","description":"AMQP delivery mode (`1` transient, `2` persistent).","example":2},"connection_pool_size":{"type":"integer","description":"Stored connection pool size. Present only when set.","example":50},"worker_count":{"type":"integer","description":"Stored worker count. Present only when set.","example":50},"queue_buffer_size":{"type":"integer","description":"Stored buffer size. Present only when set.","example":100000},"batch_size":{"type":"integer","description":"Stored batch size. Present only when set.","example":500},"batch_timeout_ms":{"type":"integer","description":"Stored batch timeout in milliseconds. Present only when set.","example":100},"publish_timeout_ms":{"type":"integer","description":"Stored publish timeout in milliseconds. Present only when set.","example":5000},"max_retries":{"type":"integer","description":"Stored retry attempts. Present only when set.","example":3},"retry_delay_ms":{"type":"integer","description":"Stored retry delay in milliseconds. Present only when set.","example":1000},"dead_letter_exchange":{"type":"string","description":"Dead-letter exchange. Present only when non-empty.","example":"dlx.zigzapy"},"dead_letter_routing_key":{"type":"string","description":"Dead-letter routing key. Present only when non-empty.","example":"dlq.events"},"message_ttl":{"type":"integer","format":"int64","description":"Message TTL in milliseconds. Present only when greater than 0.","example":86400000},"max_length":{"type":"integer","format":"int64","description":"Maximum queue length. Present only when greater than 0.","example":100000},"max_length_bytes":{"type":"integer","format":"int64","description":"Maximum queue size in bytes. Present only when greater than 0.","example":104857600},"queue_arguments":{"type":"string","description":"JSON-encoded extra queue arguments. Present only when non-empty.","example":"{\"x-overflow\":\"reject-publish\"}"},"exchange_arguments":{"type":"string","description":"JSON-encoded extra exchange arguments. Present only when non-empty.","example":"{}"}}},"SessionRabbitMQQueueStats":{"type":"object","nullable":true,"description":"In-memory queue statistics of this process for the instance. Reset on restart; `null` when the RabbitMQ manager is not running.","properties":{"userID":{"type":"string","description":"Instance (user) ID.","example":"4e4942c7dee1deef99ab8fd9f7350de5"},"dynamicQueues":{"type":"boolean","description":"Whether the instance uses per-event dynamic queues.","example":true},"createdQueues":{"type":"integer","description":"Number of queues declared by this process.","example":2},"queueNames":{"type":"array","description":"Names of the queues declared by this process.","items":{"type":"string"},"example":["user_4e4942c7dee1deef99ab8fd9f7350de5_event_Message","user_4e4942c7dee1deef99ab8fd9f7350de5_event_ReadReceipt"]}}},"SessionRabbitMQConfigSaveResponse":{"description":"Success envelope of `POST /session/rabbitmq/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Save confirmation.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"RabbitMQ configuration saved successfully"},"Enabled":{"type":"boolean","description":"Echo of the saved `enabled` value.","example":true}}}}}]},"SessionRabbitMQConfigGetResponse":{"description":"Success envelope of `GET /session/rabbitmq/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored configuration and queue statistics.","properties":{"config":{"$ref":"#/components/schemas/SessionRabbitMQConfigView"},"stats":{"$ref":"#/components/schemas/SessionRabbitMQQueueStats"}}}}}]},"SessionRabbitMQConfigDeleteResponse":{"description":"Success envelope of `DELETE /session/rabbitmq/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Delete confirmation.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"RabbitMQ configuration deleted successfully"}}}}}]},"SessionRabbitMQTestResponse":{"description":"Success envelope of `POST /session/rabbitmq/test`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Effective configuration used by the test.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"RabbitMQ connection test successful"},"Exchange":{"type":"string","description":"Exchange declared and used for the test message.","example":"whatsapp.events"},"ExchangeType":{"type":"string","description":"Exchange type used.","example":"topic"},"Queue":{"type":"string","description":"Queue name or pattern used.","example":"user_{user_id}_event_{event_type}"},"QueueType":{"type":"string","description":"Queue type used.","example":"quorum"},"RoutingKey":{"type":"string","description":"Routing key or pattern used.","example":"whatsapp.{user_id}.{event_type}"},"TestMessage":{"type":"string","description":"Confirmation that the test event was published.","example":"Test message published successfully"},"URL":{"type":"string","description":"Always `***`; the broker URL is never returned.","example":"***"}}}}}]},"SessionSkipMediaUpdateResponse":{"description":"Success envelope of `POST /session/skipmedia/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored media skip flag.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip media download configuration updated successfully"},"SkipMediaDownload":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionSkipMediaGetResponse":{"description":"Success envelope of `GET /session/skipmedia/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Per-instance and server-wide media skip settings.","properties":{"UserSkipMediaDownload":{"type":"boolean","description":"Per-instance value stored with `POST /session/skipmedia/config`.","example":true},"GlobalSkipMediaDownload":{"type":"boolean","description":"Value of the `GLOBAL_SKIP_MEDIA_DOWNLOAD` environment variable (read-only).","example":false},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip media download configuration retrieved successfully"}}}}}]},"SessionSkipGroupsUpdateResponse":{"description":"Success envelope of `POST /session/skipgroups/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored group skip flag.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip groups configuration updated successfully"},"SkipGroups":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionSkipGroupsGetResponse":{"description":"Success envelope of `GET /session/skipgroups/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Per-instance group skip flag.","properties":{"SkipGroups":{"type":"boolean","description":"Whether group events are dropped for this instance.","example":true},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip groups configuration retrieved successfully"}}}}}]},"SessionSkipNewslettersUpdateResponse":{"description":"Success envelope of `POST /session/skipnewsletters/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored newsletter skip flag.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip newsletters configuration updated successfully"},"SkipNewsletters":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionSkipNewslettersGetResponse":{"description":"Success envelope of `GET /session/skipnewsletters/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Per-instance newsletter skip flag.","properties":{"SkipNewsletters":{"type":"boolean","description":"Whether newsletter events are dropped for this instance.","example":false},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip newsletters configuration retrieved successfully"}}}}}]},"SessionSkipBroadcastsUpdateResponse":{"description":"Success envelope of `POST /session/skipbroadcasts/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored broadcast skip flag.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip broadcasts configuration updated successfully"},"SkipBroadcasts":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionSkipBroadcastsGetResponse":{"description":"Success envelope of `GET /session/skipbroadcasts/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Per-instance broadcast skip flag.","properties":{"SkipBroadcasts":{"type":"boolean","description":"Whether broadcast and Status events are dropped for this instance.","example":true},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip broadcasts configuration retrieved successfully"}}}}}]},"SessionSkipOwnMessagesUpdateResponse":{"description":"Success envelope of `POST /session/skipownmessages/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored own-message skip flag.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip own messages configuration updated successfully"},"SkipOwnMessages":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionSkipOwnMessagesGetResponse":{"description":"Success envelope of `GET /session/skipownmessages/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Per-instance own-message skip flag.","properties":{"SkipOwnMessages":{"type":"boolean","description":"Whether events about this account's own messages are dropped.","example":false},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip own messages configuration retrieved successfully"}}}}}]},"SessionSkipCallsUpdateResponse":{"description":"Success envelope of `POST /session/skipcalls/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored auto-reject settings, including applied defaults.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip calls configuration updated successfully"},"SkipCalls":{"type":"boolean","description":"Stored per-instance value.","example":true},"RejectMessage":{"type":"string","description":"Stored message sent to callers (default applied when empty).","example":"Sorry, I cannot take calls right now. Please send a message."},"RejectType":{"type":"string","description":"Stored rejection label (default `busy` applied when empty).","example":"busy"}}}}}]},"SessionSkipCallsGetResponse":{"description":"Success envelope of `GET /session/skipcalls/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored auto-reject settings.","properties":{"SkipCalls":{"type":"boolean","description":"Whether incoming calls are rejected automatically.","example":true},"RejectMessage":{"type":"string","description":"Message sent to callers after rejection.","example":"Sorry, I cannot take calls right now. Please send a message."},"RejectType":{"type":"string","description":"Stored rejection label.","example":"busy"},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Skip calls configuration retrieved successfully"}}}}}]},"EchoAPISettingsUpdateResponse":{"description":"Success envelope of `POST /session/echo/api`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored echo flag.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Echo API messages configuration updated successfully"},"EchoAPIMessages":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionPresenceConfigRequest":{"type":"object","description":"Automatic \"unavailable\" presence setting.","properties":{"enabled":{"type":"boolean","description":"`true` sends `unavailable` 3 seconds after the post-connection `available` presence; `false` stays available. Omitted is treated as `false`.","example":true}}},"SessionPresenceConfigUpdateResponse":{"description":"Success envelope of `POST /session/presence/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored presence setting.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Auto presence unavailable configuration updated successfully"},"AutoPresenceUnavailable":{"type":"boolean","description":"Stored per-instance value.","example":true}}}}}]},"SessionPresenceConfigGetResponse":{"description":"Success envelope of `GET /session/presence/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored presence setting.","properties":{"AutoPresenceUnavailable":{"type":"boolean","description":"Whether `unavailable` is sent 3 seconds after connecting.","example":true},"Details":{"type":"string","description":"Human-readable confirmation.","example":"Auto presence unavailable configuration retrieved successfully"}}}}}]},"WebhookGetResponse":{"description":"Success envelope of `GET /webhook`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored webhook configuration.","properties":{"webhook":{"type":"string","description":"Individual webhook URL; empty when not configured.","example":"https://example.com/webhooks/whatsapp"},"subscribe":{"type":"array","description":"Subscribed event types. `[\"\"]` when nothing is stored.","items":{"type":"string"},"example":["Message","ReadReceipt","Connected"]}}}}}]},"WebhookSetResponse":{"description":"Success envelope of `POST /webhook`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored webhook URL.","properties":{"webhook":{"type":"string","description":"URL stored for the instance; empty when cleared.","example":"https://example.com/webhooks/whatsapp"}}}}}]},"WebhookUpdateResponse":{"description":"Success envelope of `PUT /webhook`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the update.","properties":{"webhook":{"type":"string","description":"Stored URL; empty when `active` is false.","example":"https://example.com/webhooks/whatsapp"},"events":{"type":"array","nullable":true,"description":"Accepted event types from the request; `null` when none was sent or accepted.","items":{"type":"string"},"example":["Message","ReadReceipt"]},"active":{"type":"boolean","description":"Echo of the requested `active` value.","example":true}}}}}]},"WebhookDeleteResponse":{"description":"Success envelope of `DELETE /webhook`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Delete confirmation.","properties":{"Details":{"type":"string","description":"Human-readable confirmation.","example":"Webhook and events deleted successfully"}}}}}]},"NewsletterLegacyErrorEnvelope":{"type":"object","description":"Error response of newsletter handlers that mix two shapes: the standard error envelope (`error` set, `success: false`) and a legacy envelope where the failure is inside `data` and the top-level `success` stays `true`.","required":["code","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":500},"error":{"type":"string","description":"Error message. Present only in the standard error envelope.","example":"no session"},"data":{"type":"object","description":"Legacy failure payload. Present only in the legacy envelope.","properties":{"success":{"type":"boolean","description":"Always `false` in the legacy failure payload.","example":false},"message":{"type":"string","description":"Failure message produced by the gateway.","example":"Error listing newsletters: websocket not connected"}}},"success":{"type":"boolean","description":"`false` in the standard error envelope; `true` in the legacy envelope (check `data.success`).","example":false}}},"NewsletterText":{"type":"object","description":"Versioned text field of the raw channel metadata.","properties":{"text":{"type":"string","description":"Current text value.","example":"Product Updates"},"id":{"type":"string","description":"Version ID of this text.","example":"1757900000123456"},"update_time":{"type":"string","description":"Last update time in Unix microseconds, as a string.","example":"1757900000123456"}}},"NewsletterPictureInfo":{"type":"object","description":"Channel picture handle returned by WhatsApp.","properties":{"url":{"type":"string","description":"Download URL of the picture.","example":"https://mmg.whatsapp.net/v/t61.24694-24/example-channel-picture.jpg"},"id":{"type":"string","description":"Picture ID.","example":"1757900001"},"type":{"type":"string","description":"`image` for the full picture, `preview` for the thumbnail.","example":"image"},"direct_path":{"type":"string","description":"CDN direct path of the picture.","example":"/v/t61.24694-24/example-channel-picture.jpg"},"hash":{"type":"string","format":"byte","nullable":true,"description":"Picture hash as base64, or `null` when WhatsApp does not send it.","example":null}}},"NewsletterRawMetadata":{"type":"object","description":"One channel as returned by WhatsApp (`types.NewsletterMetadata`).","properties":{"id":{"type":"string","description":"Channel JID.","example":"120363000000000022@newsletter"},"state":{"type":"object","description":"Channel state.","properties":{"type":{"type":"string","description":"`active`, `suspended` or `geosuspended`.","example":"active"}}},"thread_metadata":{"type":"object","description":"Channel profile data.","properties":{"creation_time":{"type":"string","description":"Creation time in Unix seconds, as a string (`\"0\"` when unknown).","example":"1757900000"},"invite":{"type":"string","description":"Invite code used in `https://whatsapp.com/channel/` links.","example":"0029VaExampleInviteCode01"},"name":{"$ref":"#/components/schemas/NewsletterText"},"description":{"$ref":"#/components/schemas/NewsletterText"},"subscribers_count":{"type":"string","description":"Number of followers, as a string.","example":"1500"},"verification":{"type":"string","description":"`verified` or `unverified`.","example":"unverified"},"picture":{"$ref":"#/components/schemas/NewsletterPictureInfo"},"preview":{"$ref":"#/components/schemas/NewsletterPictureInfo"},"settings":{"type":"object","description":"Channel settings.","properties":{"reaction_codes":{"type":"object","description":"Which reactions followers may send.","properties":{"value":{"type":"string","description":"`all`, `basic`, `none` or `blocklist`.","example":"all"}}}}}}},"viewer_metadata":{"type":"object","nullable":true,"description":"This account's relation to the channel; may be `null`.","properties":{"mute":{"type":"string","description":"`on` when notifications are muted, `off` otherwise.","example":"off"},"role":{"type":"string","description":"`owner`, `admin`, `subscriber` or `guest`.","example":"owner"}}}}},"NewsletterRawListResponse":{"description":"Success envelope of `GET /newsletter/list`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Followed channels.","properties":{"Newsletter":{"type":"array","description":"Raw metadata of each followed channel; empty when the account follows no channel.","items":{"$ref":"#/components/schemas/NewsletterRawMetadata"}}}}}}]},"NewsletterCreateRequest":{"type":"object","description":"New channel data.","required":["name"],"properties":{"name":{"type":"string","minLength":1,"description":"Channel name. Cannot be blank; cut to its first 25 bytes.","example":"Product Updates"},"description":{"type":"string","description":"Optional channel description.","example":"Release notes and product news"},"picture":{"type":"string","description":"Optional channel picture as a base64 data URL or HTTP(S) URL (JPEG, PNG, GIF or WebP), converted to a JPEG of at most 640x640.","example":"https://example.com/images/channel-cover.png"}}},"NewsletterCreateResponse":{"description":"Success envelope of `POST /newsletter/create`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Created channel.","properties":{"success":{"type":"boolean","description":"Always `true` on success.","example":true},"jid":{"type":"string","description":"JID of the new channel.","example":"120363000000000022@newsletter"},"name":{"type":"string","description":"Name actually used (after the 25-byte cut).","example":"Product Updates"},"message":{"type":"string","description":"Fixed confirmation text.","example":"Newsletter created successfully"}}}}}]},"NewsletterSubscribedItem":{"type":"object","description":"One followed channel in simplified form.","properties":{"jid":{"type":"string","description":"Channel JID.","example":"120363000000000022@newsletter"},"name":{"type":"string","description":"Channel name.","example":"Product Updates"},"description":{"type":"string","description":"Channel description; empty string when not set.","example":"Release notes and product news"},"subscribers":{"type":"integer","description":"Number of followers.","example":1500},"muted":{"type":"boolean","description":"`true` when this account muted the channel notifications.","example":false},"invite_code":{"type":"string","description":"Invite code; empty string when WhatsApp does not return it.","example":"0029VaExampleInviteCode01"}}},"NewsletterSubscribedResponse":{"description":"Success envelope of `GET /newsletter/subscribed`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Followed channels.","properties":{"success":{"type":"boolean","description":"Always `true` on success.","example":true},"newsletters":{"type":"array","description":"Followed channels. Omitted when the account follows no channel.","items":{"$ref":"#/components/schemas/NewsletterSubscribedItem"}}}}}}]},"NewsletterInfoResponse":{"description":"Success envelope of `POST /newsletter/info`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Channel metadata.","properties":{"jid":{"type":"string","description":"Channel JID.","example":"120363000000000022@newsletter"},"name":{"type":"string","description":"Channel name.","example":"Product Updates"},"description":{"type":"string","description":"Channel description. Omitted when empty.","example":"Release notes and product news"},"subscribers":{"type":"integer","description":"Number of followers.","example":1500},"invite_code":{"type":"string","description":"Invite code. Omitted when empty.","example":"0029VaExampleInviteCode01"},"muted":{"type":"boolean","description":"`true` when this account muted the channel; `false` when not muted or when viewer data is unavailable.","example":false},"role":{"type":"string","description":"This account's role. Omitted when WhatsApp returns no viewer data.","enum":["owner","admin","subscriber","guest"],"example":"owner"}}}}}]},"NewsletterDeleteResponse":{"description":"Success envelope of `DELETE /newsletter/{newsletterID}`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Deletion result.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp confirmed the deletion.","example":true},"newsletter_jid":{"type":"string","description":"JID of the deleted channel.","example":"120363000000000022@newsletter"}}}}}]},"NewsletterActionResponse":{"description":"Success envelope of newsletter actions that only confirm the operation (follow, unfollow, mute, reaction, mark viewed, accept terms).","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation of the action.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the action.","example":true},"message":{"type":"string","description":"Fixed confirmation text of the operation.","example":"Subscribed successfully"}}}}}]},"NewsletterFollowInviteResponse":{"description":"Success envelope of `POST /newsletter/follow-invite`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Follow result with the resolved channel.","properties":{"success":{"type":"boolean","description":"Always `true` when the channel was followed.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Subscribed successfully"},"jid":{"type":"string","description":"JID of the channel resolved from the invite code.","example":"120363000000000022@newsletter"}}}}}]},"NewsletterMuteRequest":{"type":"object","description":"Channel and mute state to apply.","required":["jid"],"properties":{"jid":{"type":"string","description":"Channel JID (`<digits>@newsletter`). Aliases `NewsletterJID`, `newsletter_jid`, `NewsletterID`, `newsletterID`.","example":"120363000000000022@newsletter"},"mute":{"type":"boolean","description":"`true` mutes the channel notifications, `false` unmutes them. Alias `Mute`. Must be a JSON boolean; omitted or `null` unmutes.","example":true}}},"NewsletterSendRequest":{"type":"object","description":"Channel post to publish. Send `jid` plus one content type.","required":["jid"],"properties":{"jid":{"type":"string","description":"Channel JID (`<digits>@newsletter`).","example":"120363000000000022@newsletter"},"message":{"type":"string","description":"Text of a text post. Takes precedence over every other content type.","example":"Version 2.4 is live. Check the release notes on our website."},"image":{"type":"string","description":"Image as a base64 data URL or HTTP(S) URL.","example":"https://example.com/images/release-2-4.jpg"},"video":{"type":"string","description":"Video as a base64 data URL or HTTP(S) URL; the MP4 duration is detected when possible.","example":"https://example.com/videos/release-2-4.mp4"},"document":{"type":"string","description":"Document as a base64 data URL or HTTP(S) URL.","example":"https://example.com/files/release-notes-2-4.pdf"},"audio":{"type":"string","description":"Audio as a base64 data URL or HTTP(S) URL; always sent as a voice note (PTT).","example":"https://example.com/audio/weekly-briefing.ogg"},"sticker":{"type":"string","description":"Sticker (WebP) as a base64 data URL or HTTP(S) URL.","example":"https://example.com/stickers/launch.webp"},"caption":{"type":"string","description":"Caption for `image`, `video` or `document`. Ignored for other types.","example":"Version 2.4 highlights"},"filename":{"type":"string","description":"Document file name and title. Defaults to `document`.","example":"release-notes-2-4.pdf"},"question":{"type":"string","description":"Poll question. Sent as a poll only with at least 2 `options`.","example":"Which feature should ship next?"},"options":{"type":"array","description":"Poll options; at least 2.","items":{"type":"string","description":"Option text.","example":"Dark mode"},"example":["Dark mode","Offline sync"]},"max_answer":{"type":"integer","minimum":1,"default":1,"description":"How many options a follower may select. Values below 1 become 1; above the number of options returns 400.","example":1}}},"NewsletterSendResponse":{"description":"Success envelope of `POST /newsletter/send`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Published post.","properties":{"success":{"type":"boolean","description":"Always `true` when the post was sent.","example":true},"id":{"type":"string","description":"Message ID of the post (not the numeric server ID).","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"integer","format":"int64","description":"Server timestamp of the post in Unix seconds.","example":1757901234}}}}}]},"NewsletterPostMedia":{"type":"object","description":"Media details of a channel post. Present only for image, video, document, audio and sticker posts.","properties":{"type":{"type":"string","description":"Media kind.","enum":["image","video","document","audio","sticker"],"example":"image"},"mimetype":{"type":"string","description":"MIME type of the media.","example":"image/jpeg"},"url":{"type":"string","description":"Media download URL.","example":"https://mmg.whatsapp.net/v/t62.7118-24/example-post-image.jpg"},"sha256":{"type":"string","description":"SHA-256 of the file as base64.","example":"n4bQgYhMfWWaL+qgxVrQFaO/TxsrC4Is0V1sFbDwCgg="},"size":{"type":"integer","format":"int64","description":"File size in bytes.","example":48213},"title":{"type":"string","description":"Document title. Documents only.","example":"release-notes-2-4.pdf"},"duration":{"type":"integer","description":"Audio duration in seconds. Audio only.","example":34}}},"NewsletterPost":{"type":"object","description":"One channel post.","properties":{"id":{"type":"string","description":"Message ID of the post.","example":"3EB0C767D26A1D6B8A9F"},"server_id":{"type":"integer","description":"Numeric server ID used by `POST /newsletter/reaction` and `POST /newsletter/mark-viewed`.","example":121},"type":{"type":"string","description":"Stanza type attribute sent by WhatsApp, such as `text`, `media` or `poll`. Use `media.type` for the media kind.","example":"text"},"timestamp":{"type":"integer","format":"int64","description":"Post time in Unix seconds.","example":1757901234},"text":{"type":"string","description":"Text of a text post. Omitted when empty.","example":"Version 2.4 is live"},"caption":{"type":"string","description":"Caption of an image or video post. Omitted when empty.","example":"Version 2.4 highlights"},"views_count":{"type":"integer","description":"Number of views.","example":42},"reaction_counts":{"type":"object","description":"Reaction totals keyed by emoji. Omitted when there are no reactions.","additionalProperties":{"type":"integer"},"example":{"👍":3}},"media":{"$ref":"#/components/schemas/NewsletterPostMedia"}}},"NewsletterMessagesResponse":{"description":"Success envelope of `POST /newsletter/messages`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Page of channel posts.","properties":{"success":{"type":"boolean","description":"Always `true` on success.","example":true},"messages":{"type":"array","description":"Channel posts; empty when the channel has no posts in the requested range.","items":{"$ref":"#/components/schemas/NewsletterPost"}}}}}}]},"NewsletterReactionRequest":{"type":"object","description":"Reaction to set on a channel post. Unknown keys are ignored.","required":["jid","server_id"],"properties":{"jid":{"type":"string","description":"Channel JID (`<digits>@newsletter`). Aliases `NewsletterJID`, `newsletter_jid`.","example":"120363000000000022@newsletter"},"server_id":{"type":"integer","minimum":1,"description":"Positive numeric server ID of the post (number or numeric string). Alias `message_id`.","example":121},"reaction":{"type":"string","description":"Reaction emoji; an empty string, `null` or omitting it removes the reaction. Alias `emoji`.","example":"👍"}}},"NewsletterMarkViewedRequest":{"type":"object","description":"Posts to mark as viewed. Unknown keys are ignored.","required":["jid","server_ids"],"properties":{"jid":{"type":"string","description":"Channel JID (`<digits>@newsletter`). Aliases `NewsletterJID`, `newsletter_jid`.","example":"120363000000000022@newsletter"},"server_ids":{"type":"array","minItems":1,"description":"At least one positive server ID (numbers or numeric strings). Alias `message_ids`.","items":{"type":"integer","minimum":1,"description":"Server ID of a post.","example":120},"example":[120,121]}}},"NewsletterLiveUpdatesRequest":{"type":"object","description":"Channel whose live updates should be pushed to this session.","required":["jid"],"properties":{"jid":{"type":"string","description":"Channel JID (`<digits>@newsletter`). Aliases `NewsletterJID`, `newsletter_jid`, `NewsletterID`, `newsletterID`.","example":"120363000000000022@newsletter"}}},"NewsletterLiveUpdatesResponse":{"description":"Success envelope of `POST /newsletter/subscribe-live-updates`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Live updates subscription.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the subscription.","example":true},"duration":{"type":"number","description":"Subscription length in seconds as stated by WhatsApp; `0` when not stated.","example":300},"message":{"type":"string","description":"Fixed confirmation text.","example":"Subscribed to live updates"}}}}}]},"NewsletterMessageUpdatesRequest":{"type":"object","description":"Channel and cursor of the updates query. Unknown keys are ignored.","required":["jid"],"properties":{"jid":{"type":"string","description":"Channel JID (`<digits>@newsletter`). Aliases `NewsletterJID`, `newsletter_jid`.","example":"120363000000000022@newsletter"},"count":{"type":"integer","default":25,"description":"Number of posts to cover; `0`, negative or omitted means 25 and other values are passed to WhatsApp unchanged.","example":50},"since":{"type":"integer","format":"int64","minimum":0,"description":"Only changes after this Unix time (seconds).","example":1757890000},"after":{"type":"integer","minimum":0,"description":"Updates for posts newer than this server ID. Wins over `before` when both are sent.","example":120},"before":{"type":"integer","minimum":0,"description":"Updates for posts older than this server ID (exclusive). Ignored when `after` is also sent.","example":121}}},"NewsletterPostUpdateMedia":{"type":"object","description":"Reduced media details of a post update (image, video and document posts only).","properties":{"type":{"type":"string","description":"Media kind.","enum":["image","video","document"],"example":"image"},"mimetype":{"type":"string","description":"MIME type of the media.","example":"image/jpeg"},"url":{"type":"string","description":"Media download URL.","example":"https://mmg.whatsapp.net/v/t62.7118-24/example-post-image.jpg"},"title":{"type":"string","description":"Document title. Documents only.","example":"release-notes-2-4.pdf"}}},"NewsletterPostUpdate":{"type":"object","description":"Current counters of one channel post.","properties":{"id":{"type":"string","description":"Message ID of the post.","example":"3EB0C767D26A1D6B8A9F"},"server_id":{"type":"integer","description":"Numeric server ID of the post.","example":121},"type":{"type":"string","description":"Stanza type attribute sent by WhatsApp, such as `text` or `media`.","example":"text"},"timestamp":{"type":"integer","format":"int64","description":"Post time in Unix seconds.","example":1757901234},"views_count":{"type":"integer","description":"Current number of views.","example":58},"reaction_counts":{"type":"object","description":"Reaction totals keyed by emoji. Omitted when there are no reactions.","additionalProperties":{"type":"integer"},"example":{"👍":5}},"text":{"type":"string","description":"Post text when WhatsApp includes the message. Omitted when empty.","example":"Version 2.4 is live"},"caption":{"type":"string","description":"Image or video caption when included. Omitted when empty.","example":"Version 2.4 highlights"},"media":{"$ref":"#/components/schemas/NewsletterPostUpdateMedia"}}},"NewsletterMessageUpdatesResponse":{"description":"Success envelope of `POST /newsletter/message-updates`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Post updates.","properties":{"success":{"type":"boolean","description":"Always `true` on success.","example":true},"updates":{"type":"array","description":"Updates of the selected posts; empty when nothing matches.","items":{"$ref":"#/components/schemas/NewsletterPostUpdate"}}}}}}]},"NewsletterAcceptTOSRequest":{"type":"object","description":"Terms of service notice to accept. Send `{}` to accept the channel creation notice.","properties":{"notice_id":{"type":"string","default":"20601218","description":"Notice ID; `20601218` (channel creation notice) when omitted or empty.","example":"20601218"},"stage":{"type":"string","default":"5","description":"Notice stage; `5` when omitted or empty.","example":"5"}}},"NewsletterAdminInviteRequest":{"type":"object","description":"Admin invite to create and send.","required":["phone","newsletter_jid","image","caption","name"],"properties":{"phone":{"type":"string","description":"Invitee as a phone number with country code, `@s.whatsapp.net` JID or `@lid` JID.","example":"5511999999999"},"newsletter_jid":{"type":"string","description":"JID of the channel owned by this account (`<digits>@newsletter`).","example":"120363000000000022@newsletter"},"image":{"type":"string","description":"Image for the invite thumbnail, as a base64 data URL or HTTP(S) URL.","example":"https://example.com/images/channel-cover.png"},"caption":{"type":"string","description":"Invite message text.","example":"Join me as admin of Product Updates"},"name":{"type":"string","description":"Channel name shown in the invite card.","example":"Product Updates"}}},"NewsletterAdminInviteResponse":{"description":"Success envelope of `POST /newsletter/admin-invite`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Created invite and sent message.","properties":{"success":{"type":"boolean","description":"Always `true` when the invite message was sent.","example":true},"id":{"type":"string","description":"Message ID of the invite message.","example":"3EB0A1B2C3D4E5F60718"},"timestamp":{"type":"integer","format":"int64","description":"Server timestamp of the invite message (Unix seconds).","example":1757901234},"recipient":{"type":"string","description":"Echo of the `phone` field as sent.","example":"5511999999999"},"newsletter_jid":{"type":"string","description":"Echo of `newsletter_jid` as sent.","example":"120363000000000022@newsletter"},"invite_name":{"type":"string","description":"Echo of `name`.","example":"Product Updates"},"expires_at":{"type":"integer","format":"int64","description":"Invite expiration returned by WhatsApp (Unix seconds).","example":1758506034},"invitee_lid":{"type":"string","description":"LID the invite was created for and sent to.","example":"123456789012345@lid"},"invite_created":{"type":"boolean","description":"Always `true`; the server-side invite exists.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Newsletter admin invite sent successfully"}}}}}]},"GroupDetailsResponse":{"description":"Success envelope of group actions that only return a confirmation text.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation payload.","properties":{"Details":{"type":"string","description":"Fixed confirmation text of the operation.","example":"Group Name set successfully"}}}}}]},"GroupHistorySendResult":{"type":"object","description":"Server acknowledgement state of a history send. Acknowledgements do not prove that recipients received the history.","properties":{"bundle_id":{"type":"string","description":"Message ID used for the `MessageHistoryBundle` message.","example":"3EB0C767D26A1D6B8AA0"},"notice_id":{"type":"string","description":"Message ID used for the `MessageHistoryNotice` message.","example":"3EB0C767D26A1D6B8AA1"},"phase":{"type":"string","description":"Last step reached. `acknowledged` on success; otherwise the step that failed.","enum":["validation","upload","bundle","notice","acknowledged"],"example":"acknowledged"},"bundle_acknowledged":{"type":"boolean","description":"`true` when the server acknowledged the bundle message.","example":true},"notice_acknowledged":{"type":"boolean","description":"`true` when the server acknowledged the notice message.","example":true}}},"GroupHistorySendResponse":{"description":"Success envelope of `POST /group/history/send` (200). The 502 body uses `GroupHistorySendFailureResponse`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Outcome of the history send.","properties":{"success":{"type":"boolean","description":"`true` only when both messages were acknowledged. `false` on 502.","example":true},"error":{"type":"string","description":"Present only on 502. Fixed hint that the IDs must not be retried.","example":"history operation failed or remains unconfirmed; do not retry reserved IDs"},"result":{"$ref":"#/components/schemas/GroupHistorySendResult"},"retry_safe":{"type":"boolean","description":"Always `false`. The reserved IDs can never be reused.","example":false},"recipient_delivery_verified":{"type":"boolean","description":"Always `false`. Server acknowledgements do not prove recipient delivery.","example":false},"evidence_persisted":{"type":"boolean","description":"`true` when the terminal state of the reservation was stored.","example":true}}}}}]},"GroupPhotoSetResponse":{"description":"Success envelope of `POST /group/photo`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation and the new picture ID.","properties":{"Details":{"type":"string","description":"Fixed confirmation text.","example":"Group Photo set successfully"},"PictureID":{"type":"string","description":"Picture ID assigned by WhatsApp to the new photo.","example":"1757862000"}}}}}]},"GroupParticipantInfo":{"type":"object","description":"One participant of a group, as returned by WhatsApp.","properties":{"JID":{"type":"string","description":"Primary JID to address this participant; equals `LID` or `PhoneNumber`.","example":"123456789012345@lid"},"PhoneNumber":{"type":"string","description":"Phone JID when WhatsApp shares it; empty otherwise.","example":"5511999999999@s.whatsapp.net"},"LID":{"type":"string","description":"LID of the participant; empty when unknown.","example":"123456789012345@lid"},"Username":{"type":"string","description":"WhatsApp username, when the participant has one.","example":""},"IsAdmin":{"type":"boolean","description":"`true` for admins (including the super admin).","example":false},"IsSuperAdmin":{"type":"boolean","description":"`true` for the group creator/super admin.","example":false},"DisplayName":{"type":"string","description":"Obfuscated name shown for anonymous members of announcement groups; usually empty.","example":""},"Error":{"type":"integer","description":"Non-zero when WhatsApp could not add this participant during group creation (for example `403` when an invite is required).","example":0},"AddRequest":{"type":"object","nullable":true,"description":"Invite that can be sent to a participant WhatsApp refused to add directly; `null` otherwise.","properties":{"Code":{"type":"string","description":"Invite code for this participant.","example":"AbCdEfGhIjKlMnOp"},"Expiration":{"type":"string","format":"date-time","description":"When the invite code expires.","example":"2026-09-18T12:00:00Z"}}}}},"GroupInfoData":{"type":"object","description":"Group information as returned by the WhatsApp library (`types.GroupInfo`). Keys are PascalCase; unset JIDs are empty strings and unset times are `0001-01-01T00:00:00Z`.","properties":{"JID":{"type":"string","description":"Group JID.","example":"120363000000000011@g.us"},"OwnerJID":{"type":"string","description":"JID of the group creator (often a LID).","example":"123456789012340@lid"},"OwnerPN":{"type":"string","description":"Phone JID of the creator when WhatsApp shares it.","example":"5511977777777@s.whatsapp.net"},"Name":{"type":"string","description":"Group subject.","example":"Project Team"},"NameSetAt":{"type":"string","format":"date-time","description":"When the subject was last changed.","example":"2026-09-15T12:00:00Z"},"NameSetBy":{"type":"string","description":"Who last changed the subject.","example":"123456789012340@lid"},"NameSetByPN":{"type":"string","description":"Phone JID of who last changed the subject, when shared.","example":"5511977777777@s.whatsapp.net"},"Topic":{"type":"string","description":"Group description.","example":"Weekly status and deadlines"},"TopicID":{"type":"string","description":"Version ID of the description.","example":"1757937600000000"},"TopicSetAt":{"type":"string","format":"date-time","description":"When the description was last changed.","example":"2026-09-15T12:05:00Z"},"TopicSetBy":{"type":"string","description":"Who last changed the description.","example":"123456789012340@lid"},"TopicSetByPN":{"type":"string","description":"Phone JID of who last changed the description, when shared.","example":"5511977777777@s.whatsapp.net"},"TopicDeleted":{"type":"boolean","description":"`true` when the description was removed.","example":false},"IsLocked":{"type":"boolean","description":"`true` when only admins can edit group info (`POST /group/locked`).","example":true},"IsAnnounce":{"type":"boolean","description":"`true` when only admins can send messages (`POST /group/announce`).","example":false},"AnnounceVersionID":{"type":"string","description":"Version ID of the announce setting.","example":"1757937600000000"},"IsEphemeral":{"type":"boolean","description":"`true` when disappearing messages are on.","example":true},"DisappearingTimer":{"type":"integer","description":"Disappearing messages timer in seconds (`86400`, `604800`, `7776000`); `0` when off.","example":604800},"IsIncognito":{"type":"boolean","description":"Incognito flag reported by WhatsApp.","example":false},"IsParent":{"type":"boolean","description":"`true` when this group is a community (parent group).","example":false},"DefaultMembershipApprovalMode":{"type":"string","description":"Community-only default join approval mode (`request_required`); empty for regular groups.","example":""},"LinkedParentJID":{"type":"string","description":"JID of the parent community when the group is linked to one; empty otherwise.","example":"120363000000000033@g.us"},"IsDefaultSubGroup":{"type":"boolean","description":"`true` for the community announcement group.","example":false},"IsJoinApprovalRequired":{"type":"boolean","description":"`true` when new members need admin approval (`POST /group/joinapproval`).","example":true},"AddressingMode":{"type":"string","description":"How participants are addressed. `lid` groups identify people by LID.","enum":["pn","lid"],"example":"lid"},"GroupCreated":{"type":"string","format":"date-time","description":"Creation time of the group.","example":"2026-09-15T12:00:00Z"},"CreatorCountryCode":{"type":"string","description":"Country code of the creator's phone number.","example":"BR"},"ParticipantVersionID":{"type":"string","description":"Version ID of the participant list.","example":"1757937600000001"},"Participants":{"type":"array","nullable":true,"description":"Participants with admin flags. `null` when there are none to report, including every group of `GET /group/list?ignoreParticipants=true`.","items":{"$ref":"#/components/schemas/GroupParticipantInfo"}},"ParticipantCount":{"type":"integer","description":"Number of participants reported by WhatsApp.","example":12},"MemberAddMode":{"type":"string","description":"Who can add members (`POST /group/memberaddmode`). Empty when WhatsApp does not report it.","enum":["admin_add","all_member_add",""],"example":"admin_add"},"Suspended":{"type":"boolean","description":"`true` when WhatsApp suspended the group.","example":false}}},"GroupInfoResponse":{"description":"Success envelope whose `data` is one group's information.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/GroupInfoData"}}}]},"GroupListResponse":{"description":"Success envelope of `GET /group/list`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Joined groups.","properties":{"Groups":{"type":"array","nullable":true,"description":"Every joined group; `null` when the session is in no group.","items":{"$ref":"#/components/schemas/GroupInfoData"}}}}}}]},"GroupInviteLinkResponse":{"description":"Success envelope of `GET /group/invitelink`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Invite link payload.","properties":{"InviteLink":{"type":"string","description":"Full invite link of the group.","example":"https://chat.whatsapp.com/AbCdEfGhIjKlMnOpQrStUv"}}}}}]},"CommunityLinkRequest":{"type":"object","description":"Community and the group to link to it.","required":["parent_group","child_group"],"properties":{"parent_group":{"type":"string","description":"Community (parent group) JID.","example":"120363000000000033@g.us"},"child_group":{"type":"string","description":"JID of the group to link as a sub-group.","example":"120363000000000011@g.us"}}},"CommunityLinkResponse":{"description":"Success envelope of `POST /community/link`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Link confirmation.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Group linked to community successfully"},"parent_group":{"type":"string","description":"Normalized community JID.","example":"120363000000000033@g.us"},"child_group":{"type":"string","description":"Normalized sub-group JID.","example":"120363000000000011@g.us"}}}}}]},"CommunityUnlinkRequest":{"type":"object","description":"Group to remove from its community.","required":["group"],"properties":{"group":{"type":"string","description":"JID of the linked sub-group. Its parent community is looked up automatically.","example":"120363000000000011@g.us"}}},"CommunityUnlinkResponse":{"description":"Success envelope of `POST /community/unlink`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Unlink confirmation.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Group unlinked from community successfully"},"group":{"type":"string","description":"Normalized JID of the unlinked group.","example":"120363000000000011@g.us"}}}}}]},"CommunityRequestsUpdateRequest":{"type":"object","description":"Pending requests to approve or reject.","required":["group","action","requests"],"properties":{"group":{"type":"string","description":"Group or community JID.","example":"120363000000000011@g.us"},"action":{"type":"string","description":"Case-insensitive. `approve`/`accept` approve the requests; `reject`/`deny` reject them.","enum":["approve","accept","reject","deny"],"example":"approve"},"requests":{"type":"array","minItems":1,"description":"Requesters to update (LIDs, phone JIDs or phone numbers).","items":{"type":"string","description":"Requester JID or phone number.","example":"123456789012345@lid"},"example":["123456789012345@lid","5511988888888@s.whatsapp.net"]},"link_code":{"type":"string","description":"Accepted for compatibility but ignored by the gateway.","example":"AbCdEfGhIjKlMnOp"}}},"CommunityRequestsUpdateResponse":{"description":"Success envelope of `POST /community/requests/update`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Update confirmation; per-request results are not included.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Built as `Successfully <action>ed <n> request(s)` from the raw `action` value.","example":"Successfully rejected 1 request(s)"},"group":{"type":"string","description":"Normalized group JID.","example":"120363000000000011@g.us"},"action":{"type":"string","description":"The `action` exactly as sent.","example":"reject"},"requests":{"type":"array","description":"The `requests` array exactly as sent.","items":{"type":"string","description":"Requester as sent.","example":"5511988888888@s.whatsapp.net"},"example":["5511988888888@s.whatsapp.net"]}}}}}]},"SessionConnectResponse":{"description":"Success envelope of `POST /session/connect` and `POST /connector/connect`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored values of the instance after the subscription update.","properties":{"details":{"type":"string","description":"Fixed confirmation text.","example":"Connected!"},"events":{"type":"string","description":"New comma-separated event subscription. Empty when no individual webhook event is subscribed.","example":"Message,ReadReceipt,Connected"},"jid":{"type":"string","description":"Device JID stored before this call; empty before the first pairing.","example":"5511999999999:12@s.whatsapp.net"},"skip_media_download":{"type":"boolean","description":"Current value of the skip-media-download flag used by the new client.","example":false},"webhook":{"type":"string","description":"Individual webhook URL stored for the instance; empty when none is set.","example":"https://example.com/webhook"}}}}}]},"SessionDisconnectResponse":{"description":"Success envelope of `POST /session/disconnect` and `POST /connector/disconnect`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Client state before the disconnect.","properties":{"Details":{"type":"string","description":"Fixed confirmation text.","example":"Disconnected successfully"},"wasConnected":{"type":"boolean","description":"Whether the socket was connected before the call.","example":true},"wasLoggedIn":{"type":"boolean","description":"Whether the device was paired (logged in) before the call.","example":true}}}}}]},"SessionLogoutResponse":{"description":"Success envelope of `POST /session/logout`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the logout and the client state before it.","properties":{"Details":{"type":"string","description":"Fixed confirmation text.","example":"Logout completed"},"logoutSuccess":{"type":"boolean","description":"`true` when WhatsApp confirmed the device removal, or when the client was not logged in. `false` when the logout request failed; the local session is removed anyway.","example":true},"wasConnected":{"type":"boolean","description":"Whether the socket was connected before the call.","example":true},"wasLoggedIn":{"type":"boolean","description":"Whether the device was paired before the call.","example":true}}}}}]},"SessionRefreshRequest":{"type":"object","description":"Optional steps of `POST /session/refresh`. Every flag defaults to `true` when omitted.","properties":{"sync_app_state":{"type":"boolean","default":true,"description":"Fetch the five app-state collections from scratch after reconnecting.","example":true},"refresh_prekeys":{"type":"boolean","default":true,"description":"Read the server pre-key count and upload new keys when fewer than 5 remain.","example":true},"refresh_privacy":{"type":"boolean","default":true,"description":"Fetch the privacy settings from WhatsApp bypassing the cache.","example":true},"auto_recovery":{"type":"boolean","default":true,"description":"When an app-state collection fails, ask the primary phone for a recovery snapshot.","example":true}}},"SessionRefreshData":{"type":"object","description":"Result of a session refresh.","properties":{"Details":{"type":"string","description":"Fixed text, also present when the refresh failed.","example":"Connection refresh completed"},"refreshSuccess":{"type":"boolean","description":"`true` when the new client is connected after the 3-second wait.","example":true},"wasConnected":{"type":"boolean","description":"Socket state before the refresh.","example":true},"wasLoggedIn":{"type":"boolean","description":"Login state before the refresh.","example":true},"newConnected":{"type":"boolean","description":"Socket state after the wait.","example":true},"newLoggedIn":{"type":"boolean","description":"Login state after the wait.","example":true},"jid":{"type":"string","description":"Stored device JID used to reconnect.","example":"5511999999999:12@s.whatsapp.net"},"error":{"type":"string","description":"Present only when `refreshSuccess` is false.","example":"Failed to refresh connection"},"sync_options":{"type":"object","description":"Effective flags. Present only when the refresh succeeded and at least one step was enabled.","properties":{"sync_app_state":{"type":"boolean","description":"Effective `sync_app_state` flag.","example":true},"refresh_prekeys":{"type":"boolean","description":"Effective `refresh_prekeys` flag.","example":true},"refresh_privacy":{"type":"boolean","description":"Effective `refresh_privacy` flag.","example":true},"auto_recovery":{"type":"boolean","description":"Effective `auto_recovery` flag.","example":true}}},"sync":{"type":"object","description":"Results of the sync steps. Present under the same condition as `sync_options`; blocks of disabled steps are omitted.","properties":{"app_state":{"type":"array","description":"One entry per app-state collection, in fetch order.","items":{"type":"object","description":"Fetch result of one collection.","properties":{"name":{"type":"string","description":"Collection name.","enum":["critical_block","critical_unblock_low","regular_low","regular_high","regular"],"example":"regular_high"},"success":{"type":"boolean","description":"Whether the collection was fetched and applied.","example":false},"error":{"type":"string","description":"Fetch error text; omitted on success.","example":"failed to verify patch v42: mismatching LTHash"},"duration":{"type":"string","description":"Time spent on this collection (Go duration format).","example":"412.9ms"},"recovery_requested":{"type":"boolean","description":"`true` when a recovery request was sent to the primary phone; omitted otherwise.","example":true},"recovery_skipped":{"type":"boolean","description":"`true` when the recovery request was not sent because one was already sent for this collection in the last 2 minutes (the primary phone stops answering repeated requests). Omitted otherwise.","example":true}}}},"app_state_success":{"type":"boolean","description":"`true` when every collection succeeded; omitted when false.","example":true},"prekeys":{"type":"object","description":"Pre-key check result.","properties":{"checked":{"type":"boolean","description":"Whether the pre-key step ran.","example":true},"server_count":{"type":"integer","description":"Pre-keys left on the server; omitted when zero or when the count failed.","example":47},"upload_triggered":{"type":"boolean","description":"`true` when fewer than 5 keys remained and an upload was started; omitted otherwise.","example":false},"error":{"type":"string","description":"Error text when the count could not be read.","example":"failed to get server prekey count: context deadline exceeded"}}},"privacy_settings":{"type":"object","description":"Privacy settings fetch result.","properties":{"fetched":{"type":"boolean","description":"Whether the settings were fetched.","example":true},"error":{"type":"string","description":"Error text when the fetch failed.","example":"failed to fetch privacy settings: info query timed out"}}},"total_duration":{"type":"string","description":"Total time spent on the sync steps (Go duration format).","example":"4.521s"}}}}},"SessionRefreshResponse":{"description":"Success envelope of `POST /session/refresh`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SessionRefreshData"}}}]},"SessionRefreshFailureResponse":{"type":"object","description":"Body of a 500 from `POST /session/refresh`. A client that did not reconnect uses the legacy envelope (`success: true`, `data` filled, no top-level `error`); an encoding failure uses the error envelope (`success: false`, `error` filled).","properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":500},"data":{"$ref":"#/components/schemas/SessionRefreshData"},"error":{"type":"string","description":"Error text; only on the encoding failure path.","example":"json: unsupported value: NaN"},"success":{"type":"boolean","description":"`true` on the legacy not-reconnected body, `false` on the error envelope.","example":true}}},"SessionStatusS3Config":{"type":"object","description":"S3 block of the session status. The secret key is never included. When the database read fails only `enabled: false` is returned.","properties":{"enabled":{"type":"boolean","description":"Whether per-instance S3 storage is enabled.","example":true},"endpoint":{"type":"string","description":"S3-compatible endpoint URL.","example":"https://s3.us-east-1.amazonaws.com"},"region":{"type":"string","description":"Bucket region.","example":"us-east-1"},"bucket":{"type":"string","description":"Bucket name.","example":"example-whatsapp-media"},"access_key":{"type":"string","description":"Access key ID as stored.","example":"AKIAIOSFODNN7EXAMPLE"},"path_style":{"type":"boolean","description":"Whether path-style URLs are used (MinIO and similar).","example":false},"public_url":{"type":"string","description":"Public base URL used to build media links.","example":"https://cdn.example.com"},"media_delivery":{"type":"string","description":"How media reaches webhooks (`base64`, `s3` or `both`).","example":"both"},"retention_days":{"type":"integer","description":"Object retention in days; 0 keeps objects forever.","example":30},"disable_acl":{"type":"boolean","description":"Whether uploads skip the object ACL.","example":true}}},"SessionStatusRabbitMQConfig":{"type":"object","description":"RabbitMQ block of the session status, as stored. When the database read fails only `enabled: false` is returned.","properties":{"enabled":{"type":"boolean","description":"Whether the per-instance RabbitMQ transport is enabled.","example":true},"url":{"type":"string","description":"AMQP URL as stored, credentials included.","example":"amqp://guest:guest@rabbitmq.example.com:5672/"},"exchange":{"type":"string","description":"Exchange name.","example":"whatsapp.events"},"exchange_type":{"type":"string","description":"Exchange type.","example":"topic"},"queue":{"type":"string","description":"Queue name.","example":"whatsapp.instance.events"},"queue_type":{"type":"string","description":"Queue type.","example":"classic"},"routing_key":{"type":"string","description":"Routing key template.","example":"whatsapp.{event_type}"},"events":{"type":"string","description":"Comma-separated event types published to RabbitMQ.","example":"Message,ReadReceipt"},"durable":{"type":"boolean","description":"Whether the queue is durable.","example":true},"auto_delete":{"type":"boolean","description":"Whether the queue is auto-deleted.","example":false},"exclusive":{"type":"boolean","description":"Whether the queue is exclusive.","example":false},"no_wait":{"type":"boolean","description":"Whether declarations use no-wait.","example":false},"delivery_mode":{"type":"integer","description":"AMQP delivery mode (1 transient, 2 persistent).","example":2},"dead_letter_exchange":{"type":"string","description":"`x-dead-letter-exchange` queue argument.","example":"dlx.whatsapp"},"dead_letter_routing_key":{"type":"string","description":"`x-dead-letter-routing-key` queue argument.","example":"dlq.events"},"message_ttl":{"type":"integer","description":"`x-message-ttl` in milliseconds; 0 when unset.","example":86400000},"max_length":{"type":"integer","description":"`x-max-length`; 0 when unset.","example":100000},"max_length_bytes":{"type":"integer","description":"`x-max-length-bytes`; 0 when unset.","example":104857600},"queue_arguments":{"type":"string","description":"Extra queue arguments as a raw JSON string.","example":"{\"x-overflow\":\"reject-publish\"}"},"exchange_arguments":{"type":"string","description":"Extra exchange arguments as a raw JSON string.","example":"{}"}}},"SessionStatusTransportSkips":{"type":"object","description":"Per-instance flags that exclude this instance from each global transport.","properties":{"skipGlobalWebhook":{"type":"boolean","description":"Skip the global webhook.","example":false},"skipGlobalRabbitMQ":{"type":"boolean","description":"Skip the global RabbitMQ transport.","example":false},"skipGlobalSQS":{"type":"boolean","description":"Skip the global SQS transport.","example":false},"skipGlobalRedis":{"type":"boolean","description":"Skip the global Redis transport.","example":false},"skipGlobalWebSocket":{"type":"boolean","description":"Skip the global WebSocket transport.","example":false},"skipGlobalS3":{"type":"boolean","description":"Skip the global S3 upload.","example":false}}},"SessionStatusResponse":{"description":"Success envelope of `GET /session/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SessionStatus"}}}]},"SessionPairPhoneResponse":{"description":"Success envelope of `POST /session/pairphone` and `POST /connector/pairphone`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Linking code to type on the phone.","properties":{"LinkingCode":{"type":"string","description":"8-character code formatted as `XXXX-XXXX`.","example":"9H3J-H3J8"}}}}}]},"SessionQRResponse":{"description":"Success envelope of `GET /session/qr` and `GET /connector/qr`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Current pairing QR code.","properties":{"QRCode":{"type":"string","description":"PNG image of the QR code as a `data:image/png;base64,` URL; empty until generated.","example":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAA"},"code":{"type":"string","description":"Raw text encoded in the QR image; empty until generated.","example":"2@Xq3example0000QrTextValue,Zq9exampleNoiseKey=,Kp2exampleIdentityKey=,Tt5exampleAdvSecret=,1"}}}}}]},"SessionProxyRequest":{"type":"object","description":"Legacy proxy settings for `POST /session/proxy`.","properties":{"enable":{"type":"boolean","default":false,"description":"`true` stores `proxy_url`; `false` or omitted removes the proxy.","example":true},"proxy_url":{"type":"string","description":"Proxy URL, required when `enable` is true. Schemes `http`, `https` or `socks5`.","example":"socks5://proxyuser:proxypass@proxy.example.com:1080"}}},"SessionProxyResponse":{"description":"Success envelope of `POST /session/proxy`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the proxy update.","properties":{"Details":{"type":"string","description":"`Proxy configured successfully` or `Proxy disabled successfully`.","example":"Proxy configured successfully"},"ProxyURL":{"type":"string","description":"Stored URL; only when enabling.","example":"socks5://proxyuser:proxypass@proxy.example.com:1080"},"RequiresReconnection":{"type":"boolean","description":"`true` only for a connected client, which this endpoint rejects, so `false` in practice.","example":false},"Message":{"type":"string","description":"Reconnection hint; only when `RequiresReconnection` is true.","example":"Please disconnect and reconnect to apply proxy settings"}}}}}]},"SessionPasskeyAllowedCredential":{"type":"object","description":"Credential accepted for the WebAuthn ceremony.","properties":{"id":{"type":"string","description":"Credential ID, base64url without padding.","example":"Y3JlZGVudGlhbC1pZC0wMDAx"},"type":{"type":"string","description":"Credential type.","example":"public-key"},"transports":{"type":"array","description":"Transports hinted by WhatsApp; may be null.","items":{"type":"string","description":"WebAuthn transport name.","example":"internal"},"example":["internal","hybrid"]}}},"SessionPasskeyPublicKey":{"type":"object","nullable":true,"description":"WebAuthn `PublicKeyCredentialRequestOptions` sent by WhatsApp. Pass it verbatim to `navigator.credentials.get({publicKey})`.","properties":{"challenge":{"type":"string","description":"Challenge bytes, base64url without padding.","example":"ZmljdGl0aW91cy13ZWJhdXRobi1jaGFsbGVuZ2U"},"timeout":{"type":"integer","description":"Ceremony timeout in milliseconds.","example":60000},"rpId":{"type":"string","description":"Relying party ID; always sent by WhatsApp, never built by the client.","example":"whatsapp.com"},"allowCredentials":{"type":"array","description":"Credentials allowed for this challenge.","items":{"$ref":"#/components/schemas/SessionPasskeyAllowedCredential"}},"userVerification":{"type":"string","description":"User verification requirement.","example":"preferred"},"extensions":{"type":"object","nullable":true,"additionalProperties":true,"description":"WebAuthn extensions requested by WhatsApp; usually null.","example":null}}},"SessionPasskeyStatusData":{"type":"object","description":"In-memory passkey pairing state of the instance.","properties":{"required":{"type":"boolean","description":"`true` while a challenge is stored and not confirmed.","example":true},"challenge":{"$ref":"#/components/schemas/SessionPasskeyPublicKey"},"responseSubmitted":{"type":"boolean","description":"Whether a WebAuthn response was accepted by WhatsApp.","example":false},"confirmed":{"type":"boolean","description":"Whether pairing was confirmed. The state is cleared right after a confirm, so this is rarely observed as true.","example":false},"confirmationCode":{"type":"string","description":"Code to compare on the phone; empty until WhatsApp sends it.","example":"482913"},"skipHandoffUX":{"type":"boolean","description":"`true` when no code comparison is needed and the gateway confirms automatically.","example":false},"error":{"type":"string","description":"Last passkey error text; empty when none.","example":""}}},"SessionPasskeyStatusResponse":{"description":"Success envelope of `GET /session/passkey/status` and `GET /connector/passkey/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SessionPasskeyStatusData"}}}]},"SessionPasskeyChallengeResponse":{"description":"Success envelope of `POST /session/passkey/challenge` and `POST /connector/passkey/challenge`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Challenge stored for the instance.","properties":{"required":{"type":"boolean","description":"Always `true` on success.","example":true},"challenge":{"$ref":"#/components/schemas/SessionPasskeyPublicKey"}}}}}]},"SessionPasskeyUnavailableResponse":{"description":"503 body of the passkey challenge probe. Legacy envelope: `success` is `true` and the error code is inside `data`.","allOf":[{"$ref":"#/components/schemas/LegacyErrorEnvelope"},{"type":"object","properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":503},"data":{"type":"object","description":"Machine-readable reason.","properties":{"error":{"type":"string","description":"Error code.","enum":["not_connected","passkey_unavailable"],"example":"passkey_unavailable"},"reason":{"type":"string","description":"Human-readable explanation or the upstream error text.","example":"info query returned status 404: item-not-found"}}},"success":{"type":"boolean","description":"Always `true` on this legacy body, even though the status is 503.","example":true}}}]},"SessionPasskeySubmitResponse":{"description":"Success envelope of `POST /session/passkey/response` and `POST /connector/passkey/response`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Submission result.","properties":{"status":{"type":"string","description":"Always `submitted`.","example":"submitted"},"details":{"type":"string","description":"Next-step hint.","example":"Passkey response sent to WhatsApp. Await confirmation."}}}}}]},"SessionPasskeyConfirmResponse":{"description":"Success envelope of `POST /session/passkey/confirm` and `POST /connector/passkey/confirm`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation result.","properties":{"status":{"type":"string","description":"Always `confirmed`.","example":"confirmed"},"details":{"type":"string","description":"Next-step hint.","example":"Passkey confirmation sent. Pairing should complete shortly."}}}}}]},"ConnectorTokenResponse":{"description":"Success envelope of `POST /session/connector/token`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Ephemeral Connector token.","properties":{"token":{"type":"string","description":"Ephemeral token (`ct_` followed by 43 base64url characters). Send it in the `token` header or query of `/connector/*` calls.","example":"ct_Qm9ndXNFeGFtcGxlVG9rZW5WYWx1ZTAwMDAwMDAwMDAwMA"},"expiresIn":{"type":"integer","description":"Lifetime in seconds (`CONNECTOR_TOKEN_TTL`, default 600).","example":600},"tokenType":{"type":"string","description":"Always `connector`.","example":"connector"}}}}}]},"ConnectorStatusData":{"type":"object","description":"Status snapshot returned to the Connector widget: `SessionStatus` without `token`, `webhook`, `events`, `proxy_url`, `proxy_config`, `s3_config` and `rabbitmq_config`.","properties":{"id":{"type":"string","description":"Instance (user) ID.","example":"bec45bb93cbd24cbec32941ec3c93a12"},"name":{"type":"string","description":"Instance name.","example":"Support Line"},"avatar_url":{"type":"string","description":"Profile picture URL from the 24-hour cache; empty when unknown.","example":""},"connected":{"type":"boolean","description":"Whether the WhatsApp socket is connected.","example":true},"loggedIn":{"type":"boolean","description":"Whether the device is paired.","example":false},"hasClient":{"type":"boolean","description":"Whether a client exists in memory.","example":true},"connectionHealth":{"type":"string","description":"Summary derived from `hasClient`, `connected` and `loggedIn`.","enum":["no_client","disconnected","connected_not_logged","connected"],"example":"connected_not_logged"},"lastSuccessfulConnect":{"type":"integer","format":"int64","description":"Unix time of the last successful connection; 0 without a client.","example":1757862000},"autoReconnectErrors":{"type":"integer","description":"Consecutive failed automatic reconnect attempts.","example":0},"enableAutoReconnect":{"type":"boolean","description":"Whether automatic reconnect is enabled on the client.","example":true},"expiration":{"type":"integer","format":"int64","description":"Seconds until the stored expiration timestamp.","example":86400},"jid":{"type":"string","description":"Device JID; empty before pairing.","example":""},"qrcode":{"type":"string","description":"Pending QR code as a PNG data URL; empty when none is pending.","example":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEAAQMAAABmvDolAAAABlBMVEX///8AAABVwtN+AAAA"},"skip_media_download":{"type":"boolean","description":"Media is not downloaded for events.","example":false},"skip_groups":{"type":"boolean","description":"Group events are skipped.","example":false},"skip_newsletters":{"type":"boolean","description":"Newsletter events are skipped.","example":false},"skip_broadcasts":{"type":"boolean","description":"Broadcast and status events are skipped.","example":false},"skip_own_messages":{"type":"boolean","description":"Messages sent by this account are skipped.","example":false},"echo_api_messages":{"type":"boolean","description":"Messages sent through the API are echoed to transports.","example":false},"skip_calls":{"type":"boolean","description":"Call events are skipped.","example":false},"call_reject_message":{"type":"string","description":"Text sent when a call is rejected automatically.","example":""},"call_reject_type":{"type":"string","description":"Automatic call rejection mode as stored.","example":""},"globalTransportSkips":{"$ref":"#/components/schemas/SessionStatusTransportSkips"},"isFromAPI":{"type":"boolean","description":"Same value as `echo_api_messages`.","example":false},"auto_presence_unavailable":{"type":"boolean","description":"Whether the client marks itself unavailable automatically after connecting.","example":false},"passkeyRequired":{"type":"boolean","description":"`true` while a passkey challenge is stored and not confirmed.","example":false},"passkeyResponseSubmitted":{"type":"boolean","description":"Whether a WebAuthn response was already submitted.","example":false},"passkeyConfirmed":{"type":"boolean","description":"Whether the passkey pairing was confirmed.","example":false},"passkeyConfirmationCode":{"type":"string","description":"Confirmation code to compare on the phone; empty until received.","example":""},"passkeySkipHandoffUX":{"type":"boolean","description":"`true` when the gateway confirms automatically.","example":false},"passkeyError":{"type":"string","description":"Last passkey error text; empty when none.","example":""},"timestamp":{"type":"integer","format":"int64","description":"Unix time when the snapshot was built.","example":1757865600}}},"ConnectorStatusResponse":{"description":"Success envelope of `GET /connector/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConnectorStatusData"}}}]},"SessionImportResponse":{"description":"Success envelope of `POST /session/import`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Import result.","properties":{"status":{"type":"string","description":"Always `imported`.","example":"imported"},"jid":{"type":"string","description":"Device JID stored for the instance.","example":"5511999999999:12@s.whatsapp.net"},"note":{"type":"string","description":"Next-step hint.","example":"device booting (BETA); poll /session/status for loggedIn"}}}}}]},"SessionImportUnprocessableResponse":{"type":"object","description":"422 body of `POST /session/import`. Snapshot conversion errors use the error envelope (`error`, `success: false`); an incomplete generic dump uses the legacy envelope (`data`, `success: true`).","properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":422},"error":{"type":"string","description":"Conversion error; only on the error envelope.","example":"snapshot conversion failed: noiseKey: priv: expected 32 bytes, got 16"},"data":{"type":"object","description":"Extraction report; only for a generic dump.","properties":{"error":{"type":"string","description":"Fixed explanation.","example":"incomplete wa-web dump: auto-extraction could not resolve required fields"},"missing":{"type":"array","description":"Required snapshot fields that could not be resolved.","items":{"type":"string","description":"Snapshot field name.","example":"meJid"},"example":["meJid","registrationId"]},"hint":{"type":"string","description":"How to build a structured snapshot instead.","example":"supply a structured WebDeviceSnapshot (meJid, registrationId, noiseKey, identityKey, signedPreKey, account) — see docs/session-import.md"}}},"success":{"type":"boolean","description":"`false` on the error envelope, `true` on the legacy dump body.","example":false}}},"LabelManageRequest":{"type":"object","description":"Creates, edits or deletes one label.","properties":{"label_id":{"type":"string","description":"Numeric label ID. Omit to create a label with a generated ID; required when `delete` is `true`.","example":"12"},"label_name":{"type":"string","description":"Label name. Required unless `delete` is `true`.","example":"Follow-up"},"label_color":{"type":"integer","format":"int32","description":"Palette color index. Not range-checked; sent as `0` when omitted. Ignored on delete.","example":5},"delete":{"type":"boolean","default":false,"description":"`true` deletes the label identified by `label_id`.","example":false}}},"LabelManageResponse":{"description":"Success envelope of `POST /label/manage`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the label mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Label updated successfully` for create and edit, `Label deleted successfully` for delete.","example":"Label updated successfully"},"label_id":{"type":"string","description":"Label ID used in the mutation (generated or given).","example":"13"},"label_id_generated":{"type":"boolean","description":"`true` when the gateway generated `label_id`.","example":true},"label_type":{"type":"string","description":"List type sent with the mutation. Present for generated labels (`CUSTOM`) and for edits of labels observed from app state.","example":"CUSTOM"},"label_name":{"type":"string","description":"Echo of `label_name`. Omitted on delete.","example":"Hot leads"},"label_color":{"type":"integer","description":"Echo of `label_color`. Omitted on delete.","example":3}}}}}]},"LabelChatRequest":{"type":"object","description":"Applies or removes one label on one chat.","required":["phone","label_id"],"properties":{"phone":{"type":"string","description":"Chat to label. Phone number with country code (no `+`), user JID (`@s.whatsapp.net` or `@lid`) or group JID (`@g.us`).","example":"5511999999999"},"label_id":{"type":"string","description":"ID of the label to apply or remove (see `GET /label/list`).","example":"12"},"apply":{"type":"boolean","default":false,"description":"`true` applies the label, `false` removes it.","example":true}}},"LabelChatResponse":{"description":"Success envelope of `POST /label/chat`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the label association.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Label applied successfully` or `Label removed successfully`.","example":"Label applied successfully"},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"label_id":{"type":"string","description":"Echo of `label_id`.","example":"12"},"applied":{"type":"boolean","description":"Echo of `apply`.","example":true},"index_jid":{"type":"string","description":"JID written to the mutation index (LID for people when known; groups keep their JID).","example":"123456789012345@lid"}}}}}]},"LabelMessageRequest":{"type":"object","description":"Applies or removes one label on one message.","required":["phone","message_id","label_id"],"properties":{"phone":{"type":"string","description":"Chat that holds the message. Phone number, user JID or group JID.","example":"5511999999999"},"message_id":{"type":"string","description":"ID of the message to label.","example":"3EB0C767D26A1D6B8A9F"},"label_id":{"type":"string","description":"ID of the label to apply or remove.","example":"12"},"apply":{"type":"boolean","default":false,"description":"`true` applies the label, `false` removes it.","example":true}}},"LabelMessageResponse":{"description":"Success envelope of `POST /label/message`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the message label mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Label applied successfully` or `Label removed successfully`.","example":"Label applied successfully"},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"message_id":{"type":"string","description":"Echo of `message_id`.","example":"3EB0C767D26A1D6B8A9F"},"label_id":{"type":"string","description":"Echo of `label_id`.","example":"12"},"applied":{"type":"boolean","description":"Echo of `apply`.","example":true}}}}}]},"LabelListResponse":{"description":"Success envelope of `GET /label/list`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Labels known to the gateway.","properties":{"labels":{"type":"array","description":"Labels sorted by order index (numeric ID when no order index is known).","items":{"$ref":"#/components/schemas/LabelView"}},"complete":{"type":"boolean","description":"`true` only after a successful full sync (`refresh=true`).","example":true},"observed_from_app_state":{"type":"boolean","description":"`true` once at least one label was observed from app state.","example":true},"synced_at":{"type":"string","format":"date-time","description":"UTC time of the last successful full sync. Omitted when no full sync has succeeded.","example":"2026-09-15T01:39:35Z"},"note":{"type":"string","description":"Fixed reminder that message labels are not displayed by the official apps.","example":"message labels (label_message) are not shown by the official apps"}}}}}]},"LabelView":{"type":"object","description":"One label with the chats that carry it.","properties":{"id":{"type":"string","description":"Label ID.","example":"16"},"name":{"type":"string","description":"Label name.","example":"New customer"},"color":{"type":"integer","description":"Palette color index.","example":1},"deleted":{"type":"boolean","description":"`true` when the label was deleted.","example":false},"predefined_id":{"type":"integer","description":"Predefined Business label ID. Omitted when unknown.","example":1},"order_index":{"type":"integer","description":"Position in the list. Omitted when unknown.","example":10},"is_active":{"type":"boolean","description":"Whether the list is active. Omitted when unknown.","example":true},"type":{"type":"string","description":"Official list type (for example `UNREAD`, `FAVORITES`, `GROUPS`, `PREDEFINED`, `CUSTOM`). Omitted when unknown.","example":"PREDEFINED"},"is_immutable":{"type":"boolean","description":"Whether the list can be edited. Omitted when unknown.","example":false},"source":{"type":"string","description":"Where the label was last seen.","enum":["app_state","api"],"example":"app_state"},"updated_at":{"type":"string","format":"date-time","description":"Time of the last change observed or sent.","example":"2026-07-02T15:19:25-03:00"},"chats":{"type":"array","description":"Chat JIDs that carry this label (LIDs for people when known).","items":{"type":"string"},"example":["123456789012345@lid"]}}},"ChatPinRequest":{"type":"object","description":"Pins or unpins one chat in the chat list.","required":["phone"],"properties":{"phone":{"type":"string","description":"Chat to pin. Phone number with country code (no `+`), user JID (`@s.whatsapp.net` or `@lid`) or group JID (`@g.us`).","example":"5511999999999"},"pin":{"type":"boolean","default":false,"description":"`true` pins the chat, `false` unpins it.","example":true}}},"ChatPinResponse":{"description":"Success envelope of `POST /chat/pin`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the pin mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Chat pinned successfully` or `Chat unpinned successfully`.","example":"Chat pinned successfully"},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"pinned":{"type":"boolean","description":"Echo of `pin`.","example":true}}}}}]},"ChatArchiveRequest":{"type":"object","description":"Archives or unarchives one chat.","required":["phone"],"properties":{"phone":{"type":"string","description":"Chat to archive. Phone number with country code (no `+`), user JID or group JID.","example":"5511999999999"},"archive":{"type":"boolean","default":false,"description":"`true` archives the chat, `false` unarchives it.","example":true},"last_message_timestamp":{"type":"integer","format":"int64","description":"Unix time in seconds of the most recent message. Defaults to the current time.","example":1757862000},"last_message_id":{"type":"string","description":"ID of the most recent message. When omitted no message key is sent.","example":"3EB0C767D26A1D6B8A9F"},"last_message_from_me":{"type":"boolean","default":false,"description":"Whether the most recent message was sent by this account. Only used with `last_message_id`.","example":false},"last_message_remote_jid":{"type":"string","description":"Overrides the chat JID inside the message key. Only used with `last_message_id`.","example":"5511999999999@s.whatsapp.net"}}},"ChatArchiveResponse":{"description":"Success envelope of `POST /chat/archive`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the archive mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Chat archived successfully` or `Chat unarchived successfully`.","example":"Chat archived successfully"},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"archived":{"type":"boolean","description":"Echo of `archive`.","example":true}}}}}]},"ChatMuteRequest":{"type":"object","description":"Mutes or unmutes one chat.","required":["phone"],"properties":{"phone":{"type":"string","description":"Chat to mute. Phone number with country code (no `+`), user JID or group JID.","example":"5511999999999"},"mute":{"type":"boolean","default":false,"description":"`true` mutes the chat, `false` unmutes it.","example":true},"mute_duration":{"type":"string","description":"Mute length (case-insensitive). Omitted means `always`. Ignored when unmuting.","enum":["8h","1w","always"],"example":"8h"}}},"ChatMuteResponse":{"description":"Success envelope of `POST /chat/mute`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the mute mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Chat muted successfully` or `Chat unmuted successfully`.","example":"Chat muted successfully"},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"muted":{"type":"boolean","description":"Echo of `mute`.","example":true},"duration":{"type":"string","description":"Raw `mute_duration` as sent (empty when omitted). Only present when muting.","example":"8h"}}}}}]},"ChatStarRequest":{"type":"object","description":"Stars or unstars one message.","required":["chat_jid","message_id"],"properties":{"chat_jid":{"type":"string","description":"Chat that holds the message. Phone number, user JID or group JID.","example":"5511999999999@s.whatsapp.net"},"sender_jid":{"type":"string","description":"Author of the message. Needed for a message written by another participant in a group.","example":"5511888888888@s.whatsapp.net"},"message_id":{"type":"string","description":"ID of the message to star or unstar.","example":"3EB0C767D26A1D6B8A9F"},"from_me":{"type":"boolean","default":false,"description":"Whether the message was sent by this account. Must match the real author.","example":true},"star":{"type":"boolean","default":false,"description":"`true` stars the message, `false` unstars it.","example":true}}},"ChatStarResponse":{"description":"Success envelope of `POST /chat/star`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the star mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"`Message starred successfully` or `Message unstarred successfully`.","example":"Message starred successfully"},"chat_jid":{"type":"string","description":"Chat JID parsed from `chat_jid`.","example":"5511999999999@s.whatsapp.net"},"message_id":{"type":"string","description":"Echo of `message_id`.","example":"3EB0C767D26A1D6B8A9F"},"starred":{"type":"boolean","description":"Echo of `star`.","example":true},"index_chat_jid":{"type":"string","description":"Chat JID written to the mutation index (LID for people when known).","example":"123456789012345@lid"}}}}}]},"ChatDeleteChatRequest":{"type":"object","description":"Deletes one chat from the chat list.","required":["phone"],"properties":{"phone":{"type":"string","description":"Chat to delete. Phone number with country code (no `+`), user JID or group JID.","example":"5511999999999"},"last_message_timestamp":{"type":"integer","format":"int64","description":"Unix time in seconds of the most recent message. Required for the message key fields to be used.","example":1757862000},"last_message_id":{"type":"string","description":"ID of the most recent message. Only used with `last_message_timestamp`.","example":"3EB0C767D26A1D6B8A9F"},"last_message_from_me":{"type":"boolean","default":false,"description":"Whether the most recent message was sent by this account. Only used with `last_message_id`.","example":false},"last_message_sender_jid":{"type":"string","description":"Author of the most recent message. Only used for group chats with `last_message_id`.","example":"5511888888888@s.whatsapp.net"},"delete_media":{"type":"boolean","default":true,"description":"Also delete the chat's media files. Defaults to `true`.","example":true},"last_system_message_timestamp":{"type":"integer","format":"int64","description":"Unix time in seconds of the last system notice to delete (for example disappearing-messages notices). Defaults to `last_message_timestamp`, or to the current time when neither is sent.","example":1757862000}}},"ChatDeleteChatResponse":{"description":"Success envelope of `POST /chat/delete-chat`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the deleteChat mutation.","properties":{"success":{"type":"boolean","description":"Always `true` when WhatsApp accepted the mutation.","example":true},"message":{"type":"string","description":"Always `Chat deleted successfully`.","example":"Chat deleted successfully"},"jid":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"delete_media":{"type":"boolean","description":"Effective `delete_media` value (default applied).","example":true}}}}}]},"ChatPinMessageRequest":{"type":"object","description":"Pins or unpins one message for every participant of the chat.","required":["phone","message_id","from_me","pin"],"properties":{"phone":{"type":"string","description":"Chat that holds the message. Phone number, user JID or group JID.","example":"5511999999999"},"message_id":{"type":"string","description":"ID of the message to pin or unpin.","example":"3EB0C767D26A1D6B8A9F"},"from_me":{"type":"boolean","description":"Whether the target message was sent by this account.","example":true},"pin":{"type":"boolean","description":"`true` pins the message, `false` unpins it.","example":true},"sender_jid":{"type":"string","description":"Author of the message. Required in groups when `from_me` is `false`.","example":"5511888888888@s.whatsapp.net"},"duration_seconds":{"type":"integer","description":"Pin duration in seconds. Only used when `pin` is `true`.","enum":[86400,604800,2592000],"default":604800,"example":604800}}},"ChatPinMessageResponse":{"description":"Success envelope of `POST /chat/pin-message`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the pin message send.","properties":{"success":{"type":"boolean","description":"Always `true` when the message was sent.","example":true},"id":{"type":"string","description":"ID of the protocol message that carries the pin.","example":"3EB0B1C2D3E4F5A6B7C8"},"chat":{"type":"string","description":"Chat JID the pin was sent to (LID for people when known).","example":"123456789012345@lid"},"message_id":{"type":"string","description":"Echo of `message_id`.","example":"3EB0C767D26A1D6B8A9F"},"pinned":{"type":"boolean","description":"Echo of `pin`.","example":true},"timestamp":{"type":"integer","format":"int64","description":"Server timestamp of the send, in Unix seconds.","example":1757862000},"duration_seconds":{"type":"integer","description":"Effective pin duration. Only present when pinning.","example":604800}}}}}]},"ChatDownloadMediaRequest":{"type":"object","description":"Media reference copied from a `Message` webhook event (`imageMessage`, `videoMessage`, `audioMessage`, `documentMessage` or `stickerMessage`). Keys are matched case-insensitively, so the webhook object can be posted unchanged.","required":["DirectPath","MediaKey","FileEncSHA256","FileSHA256"],"properties":{"Url":{"type":"string","description":"`URL` of the media message. Accepted for compatibility but not used; the file is fetched through `DirectPath`.","example":"https://mmg.whatsapp.net/o1/v/t62.7118-24/f2/m231/AQ_example_image.enc?ccb=9-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=e6ed6c"},"DirectPath":{"type":"string","description":"`directPath` of the media message (starts with `/`). Without it the download fails with `no url present`.","example":"/o1/v/t62.7118-24/f2/m231/AQ_example_image.enc?ccb=9-4&oh=01_Q5Aa0000&oe=68F0A1B2&_nc_sid=e6ed6c"},"MediaKey":{"type":"string","format":"byte","description":"`mediaKey` of the media message, standard base64 (not hex). Used to decrypt the file.","example":"aQGcesqhANsFce2gBbNeXnE4LU9wA6LM5lA1ztbBduM="},"Mimetype":{"type":"string","description":"`mimetype` of the media message. Not validated; echoed in the response and used as the data URL media type.","example":"image/jpeg"},"FileEncSHA256":{"type":"string","format":"byte","description":"`fileEncSHA256` of the media message, standard base64: SHA-256 of the encrypted file.","example":"8wdTCF7kBugCQhneOg2YLsDye4Eqwu7N8kzyXKJXoIU="},"FileSHA256":{"type":"string","format":"byte","description":"`fileSHA256` of the media message, standard base64: SHA-256 of the decrypted file.","example":"Gc6NIzcYSI596Ke0Y0sO1VstRgq8FpAUzOglP06aYyE="},"FileLength":{"type":"integer","format":"int64","description":"`fileLength` in bytes. Accepted but not used for the download.","example":48213}}},"ChatDownloadMediaResponse":{"description":"Success envelope of the `/chat/download*` operations.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Decrypted media file.","properties":{"Mimetype":{"type":"string","description":"Echo of the request `Mimetype`.","example":"image/jpeg"},"Data":{"type":"string","description":"Whole file as a data URL (`data:<Mimetype>;base64,<file>`).","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8U"}}}}}]},"ChatDeleteMessageRequest":{"type":"object","description":"Revokes (deletes for everyone) one message.","required":["Phone","Id"],"properties":{"Phone":{"type":"string","description":"Chat that holds the message. Phone number with country code (no `+`), user JID or group JID.","example":"5511999999999"},"Id":{"type":"string","description":"ID of the message to revoke.","example":"3EB0C767D26A1D6B8A9F"},"Sender":{"type":"string","description":"Original author of the message. Only for a group admin revoking another participant's message.","example":"123456789012345@lid"}}},"ChatDeleteMessageResponse":{"description":"Success envelope of `POST /chat/delete`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the revoke.","properties":{"Details":{"type":"string","description":"Always `Deleted`.","example":"Deleted"},"Id":{"type":"string","description":"ID of the revoked message (echo of `Id`).","example":"3EB0C767D26A1D6B8A9F"},"Timestamp":{"type":"string","format":"date-time","description":"Server timestamp of the revoke.","example":"2026-09-15T10:30:00-03:00"}}}}}]},"ChatMarkReadRequest":{"type":"object","description":"Read receipt for messages of one chat and one sender.","required":["Id","Chat"],"properties":{"Id":{"type":"array","description":"Message IDs to mark as read (`event.Info.ID`). At least one; all from the same sender.","items":{"type":"string"},"example":["3EB0C767D26A1D6B8A9F","3EB0A1B2C3D4E5F60718"]},"Chat":{"type":"string","description":"Full chat JID as received (`event.Info.Chat`). Bare phone numbers are not converted.","example":"5511999999999@s.whatsapp.net"},"Sender":{"type":"string","description":"Author JID (`event.Info.Sender`). Required in groups; ignored for direct chats.","example":"123456789012345@lid"}}},"ChatMarkReadResponse":{"description":"Success envelope of `POST /chat/markread`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the receipt.","properties":{"Details":{"type":"string","description":"Always `Message(s) marked as read`.","example":"Message(s) marked as read"}}}}}]},"ChatReactRequest":{"type":"object","description":"Adds or removes a reaction on one message.","required":["Phone","Id"],"properties":{"Phone":{"type":"string","description":"Chat of the target message. Phone number for direct chats, `@g.us` JID for groups.","example":"5511999999999"},"Body":{"type":"string","description":"Reaction emoji. Empty string or `remove` removes the reaction.","example":"👍"},"Id":{"type":"string","description":"ID of the target message. Prefix with `me:` when the message was sent by this account.","example":"2AFA4C0C20D815D8055A"},"Sender":{"type":"string","description":"Full JID of the author of the target message. Only used for another participant's message in a group.","example":"123456789012345@lid"},"Chat":{"type":"string","description":"Exact chat JID from the webhook (`event.Info.Chat`). When set, used as both destination and key chat instead of `Phone`.","example":"123456789012345@lid"}}},"ChatReactResponse":{"description":"Success envelope of `POST /chat/react`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the reaction send.","properties":{"Details":{"type":"string","description":"Always `Sent`.","example":"Sent"},"Id":{"type":"string","description":"ID of the new reaction message (not the target message).","example":"3EB0D1E2F3A4B5C6D7E8"},"Timestamp":{"type":"string","format":"date-time","description":"Server timestamp of the send.","example":"2026-09-15T10:30:00-03:00"}}}}}]},"ChatPresenceStateRequest":{"type":"object","description":"Chat state (typing indicator) to send to one chat.","required":["Phone","State"],"properties":{"Phone":{"type":"string","description":"Chat to notify. Phone number, user JID or group JID.","example":"5511999999999"},"State":{"type":"string","description":"`composing` shows the indicator, `paused` clears it. Not validated by the gateway.","enum":["composing","paused"],"example":"composing"},"Media":{"type":"string","description":"`audio` shows recording audio instead of typing. Only used with `composing`.","enum":["","audio"],"example":"audio"}}},"ChatPresenceStateResponse":{"description":"Success envelope of `POST /chat/presence`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the chat state send.","properties":{"Details":{"type":"string","description":"Fixed confirmation text (spelling as returned by the gateway).","example":"Chat presence set successfuly"}}}}}]},"ChatRetryMessageRequest":{"type":"object","description":"Resend request for a message this device could not process. Keys are case-insensitive.","required":["MessageID","ChatJID"],"properties":{"MessageID":{"type":"string","description":"ID of the message to recover (`event.Info.ID`). Alias `messageId`.","example":"3EB0C767D26A1D6B8A9F"},"ChatJID":{"type":"string","description":"Chat of the message, phone number or JID. Alias `chatJid`.","example":"120363000000000011@g.us"},"SenderJID":{"type":"string","description":"Author of the message (participant in groups). Required unless `ForceRetry` is `true`. Alias `senderJid`.","example":"5511888888888@s.whatsapp.net"},"RetryType":{"type":"string","description":"Retry mode; `incoming` and `auto` behave the same. Other values return 500.","enum":["incoming","auto"],"default":"incoming","example":"incoming"},"ForceRetry":{"type":"boolean","default":false,"description":"Send the resend request even when `SenderJID` is empty.","example":false}}},"ChatRetryMessageResponse":{"description":"Success envelope of `POST /chat/retry/message`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the resend request.","properties":{"Details":{"type":"string","description":"Always `Message retry operation completed` on 200.","example":"Message retry operation completed"},"Found":{"type":"boolean","description":"Always `true` on 200; means the resend request was sent, not that the message was found.","example":true},"Sources":{"type":"array","description":"Mechanisms used; always `[\"retry_request\"]` on 200.","items":{"type":"string"},"example":["retry_request"]},"RetryAttempts":{"type":"integer","description":"Number of resend requests sent (always 1 on 200).","example":1},"RetryType":{"type":"string","description":"Effective `RetryType` (default applied).","example":"incoming"},"CacheStatus":{"type":"string","description":"Always `retry_initiated` on 200.","example":"retry_initiated"},"ProcessedAt":{"type":"string","format":"date-time","description":"Server time when the request was processed.","example":"2026-09-15T10:30:00-03:00"},"MessageData":{"type":"object","description":"Details of the resend request.","properties":{"retryMethod":{"type":"string","description":"Always `unavailable_message_request`.","example":"unavailable_message_request"},"requestedAt":{"type":"string","format":"date-time","description":"Server time when the request was sent.","example":"2026-09-15T10:30:00-03:00"},"targetChat":{"type":"string","description":"`ChatJID` as sent.","example":"120363000000000011@g.us"},"targetSender":{"type":"string","description":"`SenderJID` as sent (empty when omitted).","example":"5511888888888@s.whatsapp.net"}}}}}}}]},"ChatReplyResponse":{"description":"Success envelope of `POST /chat/reply`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the reply send.","properties":{"success":{"type":"boolean","description":"Always `true` when the reply was sent.","example":true},"message_id":{"type":"string","description":"ID of the new reply message.","example":"3EB0C767D26A1D6B8AA0"},"timestamp":{"type":"string","format":"date-time","description":"Server timestamp of the send.","example":"2026-09-15T10:30:00-03:00"},"to":{"type":"string","description":"Chat JID parsed from `to`.","example":"5511999999999@s.whatsapp.net"},"quoted_msg_id":{"type":"string","description":"Echo of `quoted_msg_id`.","example":"3EB0F2A1C9D04E8F1234"},"content_type":{"type":"string","description":"Echo of `content_type`.","example":"text"}}}}}]},"StatusSendResponse":{"description":"Success envelope of `POST /status/send/text`, `/image` and `/video`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the status send.","properties":{"message_id":{"type":"string","description":"ID of the status message.","example":"3EB06F9067F80BAB89FF"},"timestamp":{"type":"string","format":"date-time","description":"Server timestamp of the send.","example":"2026-09-15T10:30:00-03:00"},"status":{"type":"string","description":"Always `sent`.","example":"sent"},"type":{"type":"string","description":"Kind of status posted.","enum":["text_status","image_status","video_status"],"example":"text_status"}}}}}]},"StatusSendAudioResponse":{"description":"Success envelope of `POST /status/send/audio`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Result of the audio status send.","properties":{"message_id":{"type":"string","description":"ID of the status message.","example":"3EB072C49492CB69CBCBCF"},"timestamp":{"type":"string","format":"date-time","description":"Server timestamp of the send.","example":"2026-09-14T22:25:15-03:00"},"status":{"type":"string","description":"Always `sent`.","example":"sent"},"type":{"type":"string","description":"`voice_status` when `ptt` is true, `audio_status` otherwise.","enum":["voice_status","audio_status"],"example":"voice_status"},"ptt":{"type":"boolean","description":"Effective `ptt` value (default applied).","example":true},"duration":{"type":"integer","description":"Detected duration in seconds (0 when it could not be detected).","example":4},"has_waveform":{"type":"boolean","description":"Always `true`; a waveform is generated for audio statuses.","example":true},"mime_type":{"type":"string","description":"Final MIME type sent to WhatsApp after normalization.","example":"audio/ogg; codecs=opus"}}}}}]},"SyncChatListResponse":{"description":"Success envelope of `GET /chat/list`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Chats with stored settings.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"chats":{"type":"array","description":"Chats ordered pinned first, then non-archived.","items":{"type":"object","description":"Stored settings of one chat.","properties":{"chat_jid":{"type":"string","description":"Full chat JID.","example":"5511999999999@s.whatsapp.net"},"phone_number":{"type":"string","description":"User part of the JID (phone number, LID or group ID). Omitted when the JID does not parse.","example":"5511999999999"},"muted_until":{"type":"integer","format":"int64","description":"Unix time in seconds when the mute ends. Omitted when the chat is not muted.","example":1767225600},"pinned":{"type":"boolean","description":"Whether the chat is pinned.","example":true},"archived":{"type":"boolean","description":"Whether the chat is archived.","example":false}}}},"stats":{"type":"object","description":"Counters over the returned chats.","properties":{"total":{"type":"integer","description":"Number of chats returned.","example":2},"pinned_count":{"type":"integer","description":"Number of pinned chats.","example":1},"archived_count":{"type":"integer","description":"Number of archived chats.","example":1},"muted_count":{"type":"integer","description":"Number of muted chats.","example":1}}}}}}}]},"SyncAppStateRequest":{"type":"object","description":"Options of the app-state resynchronization. Every field is optional.","properties":{"full_sync":{"type":"boolean","default":true,"description":"`true` downloads full snapshots; `false` only fetches patches newer than the stored versions.","example":true},"auto_recovery":{"type":"boolean","default":true,"description":"Ask the primary phone for a recovery snapshot of each collection that fails.","example":true}}},"SyncAppStateResponse":{"description":"Success envelope of `POST /sync/app-state`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Outcome of the five collection fetches.","properties":{"success":{"type":"boolean","description":"`true` only when all five collections synchronized.","example":true},"message":{"type":"string","description":"Human-readable summary of the outcome.","example":"App state synchronized successfully. All 5 patch types updated."},"results":{"type":"array","description":"One entry per collection, in fetch order.","items":{"type":"object","description":"Outcome of one collection.","properties":{"name":{"type":"string","description":"Collection name.","enum":["critical_block","critical_unblock_low","regular_low","regular_high","regular"],"example":"regular_high"},"success":{"type":"boolean","description":"Whether this collection synchronized.","example":true},"error":{"type":"string","description":"Fetch error. Omitted on success.","example":"failed to verify patch v1234: mismatching LTHash"},"duration":{"type":"string","description":"Time spent on this collection (Go duration format).","example":"955.7ms"},"recovery_requested":{"type":"boolean","description":"`true` when a recovery request was sent for this failed collection. Omitted otherwise.","example":true},"recovery_skipped":{"type":"boolean","description":"`true` when the recovery request was not sent because one was already sent for this collection in the last 2 minutes (the primary phone stops answering repeated requests). Omitted otherwise.","example":true}}}},"auto_recovery_enabled":{"type":"boolean","description":"Effective `auto_recovery` value.","example":true}}}}}]},"SyncHistoryRequestRequest":{"type":"object","description":"Anchor message and size of an on-demand history request for one chat.","required":["phone","oldest_message_id","oldest_message_timestamp"],"properties":{"phone":{"type":"string","description":"Chat to page back. Phone number, user JID or group JID.","example":"5511999999999"},"oldest_message_id":{"type":"string","description":"ID of the oldest message already known for this chat.","example":"3EB0C767D26A1D6B8A9F"},"oldest_message_timestamp":{"type":"integer","format":"int64","description":"Timestamp of that oldest message in milliseconds since the Unix epoch. Must not be 0.","example":1757862000000},"oldest_from_me":{"type":"boolean","default":false,"description":"Whether the oldest message was sent by this account.","example":false},"count":{"type":"integer","format":"int32","default":50,"description":"Number of older messages to ask for. 0 or omitted means 50.","example":100}}},"SyncHistoryRequestResponse":{"description":"Success envelope of `POST /sync/history-request`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation of the history request.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"History sync request sent successfully. History will arrive asynchronously via HistorySync events (webhook/websocket)."},"request_id":{"type":"string","description":"Same value as `oldest_message_id`.","example":"3EB0C767D26A1D6B8A9F"},"chat":{"type":"string","description":"Chat JID parsed from `phone`.","example":"5511999999999@s.whatsapp.net"},"count":{"type":"integer","description":"Effective number of messages requested (default applied).","example":50}}}}}]},"SyncFullHistoryRequest":{"type":"object","description":"Limits of the full history sync. Every field is optional.","properties":{"days_limit":{"type":"integer","format":"int32","default":30,"description":"How many days of history to request. 0 means 30.","example":30},"size_mb_limit":{"type":"integer","format":"int32","default":1000,"description":"Size limit in megabytes, also sent as the storage quota. 0 means 1000.","example":1000},"include_groups":{"type":"boolean","default":true,"description":"Ask for group chat history too.","example":true},"include_calls":{"type":"boolean","default":false,"description":"Ask for the call log history.","example":false}}},"SyncFullHistoryResponse":{"description":"Success envelope of `POST /sync/full-history`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation of the full history request.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Full history sync requested successfully. History will arrive asynchronously via HistorySync events (webhook/websocket). This works exactly like the initial connection sync."},"request_id":{"type":"string","description":"Random 32-character uppercase hexadecimal request ID.","example":"9F3A6C1E2B7D4058A1C3E5F7092B4D6E"},"config":{"type":"object","description":"Effective limits sent to the phone (defaults applied).","properties":{"days_limit":{"type":"integer","description":"Days of history requested.","example":30},"size_mb_limit":{"type":"integer","description":"Size limit in megabytes.","example":1000},"include_groups":{"type":"boolean","description":"Whether group history was requested.","example":true},"include_calls":{"type":"boolean","description":"Whether call log history was requested.","example":false}}}}}}}]},"CallRejectLegacyResponse":{"description":"Success envelope of `POST /call/reject/send`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Rejection result.","properties":{"success":{"type":"boolean","description":"Always `true` when the rejection stanza was sent.","example":true},"call_id":{"type":"string","description":"Echo of the requested call ID.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Echo of `call_from` exactly as sent in the request.","example":"5511999999999@s.whatsapp.net"},"reject_type":{"type":"string","description":"Echo of the requested rejection label.","enum":["busy","declined","unavailable"],"example":"busy"},"action":{"type":"string","description":"Always `rejected`.","enum":["rejected"],"example":"rejected"},"message_sent":{"type":"boolean","description":"Present (always `true`) only when `message` was provided, even if sending the text failed.","example":true}}}}}],"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reject_type":"busy","action":"rejected","message_sent":true},"success":true}},"CallAcceptV1Response":{"description":"Success envelope of `POST /call/accept` and `POST /call/preaccept`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Signaling result.","properties":{"success":{"type":"boolean","description":"Always `true` when the stanza was sent.","example":true},"call_id":{"type":"string","description":"Echo of the requested call ID.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Caller JID normalized by the gateway.","example":"5511999999999@s.whatsapp.net"},"action":{"type":"string","description":"`accepted` for `/call/accept`, `preaccepted` for `/call/preaccept`.","enum":["accepted","preaccepted"],"example":"accepted"}}}}}],"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","action":"accepted"},"success":true}},"CallTerminateV1Response":{"description":"Success envelope of `POST /call/terminate`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Terminate result.","properties":{"success":{"type":"boolean","description":"Always `true` when the stanza was sent.","example":true},"call_id":{"type":"string","description":"Echo of the requested call ID.","example":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718"},"call_from":{"type":"string","description":"Other party JID normalized by the gateway.","example":"5511999999999@s.whatsapp.net"},"reason":{"type":"string","description":"Reason sent (the default `hangup` when omitted).","example":"hangup"},"action":{"type":"string","description":"Always `terminated`.","enum":["terminated"],"example":"terminated"}}}}}],"example":{"code":200,"data":{"success":true,"call_id":"3F8A2C9B1D7E4F60A1B2C3D4E5F60718","call_from":"5511999999999@s.whatsapp.net","reason":"hangup","action":"terminated"},"success":true}},"CallIdResponse":{"description":"Success envelope returned when a call is placed or joined.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"The new call tracked by the native calls engine.","properties":{"callId":{"type":"string","description":"Engine call ID; pass it to `/call/hangup`, `/call/play`, the streams and every other in-call control.","example":"call_22A9E1B7D3F84C10"}}}}}],"example":{"code":200,"data":{"callId":"call_22A9E1B7D3F84C10"},"success":true}},"CallEngineConfigResponse":{"description":"Success envelope of `GET /call/config`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Stored engine configuration. `callProviderToken` is never included.","properties":{"callsEnabled":{"type":"boolean","description":"Whether the engine runs for this instance after a reconnect.","example":true},"callInboundMode":{"type":"string","description":"Inbound handling mode (`webhook` when unset).","enum":["manual","bot","ivr","ai","webhook","reject"],"example":"webhook"},"callRecord":{"type":"boolean","description":"Whether connected calls are recorded automatically.","example":true},"callSttUrl":{"type":"string","description":"Speech-to-text endpoint, empty when unset.","example":""},"callLlmUrl":{"type":"string","description":"Language-model endpoint, empty when unset.","example":""},"callTtsUrl":{"type":"string","description":"Text-to-speech endpoint, empty when unset.","example":""},"callSystemPrompt":{"type":"string","description":"Voice-agent system prompt, empty when unset.","example":""},"callGreeting":{"type":"string","description":"Voice-agent greeting, empty when unset.","example":""}}}}}],"example":{"code":200,"data":{"callsEnabled":true,"callInboundMode":"webhook","callRecord":true,"callSttUrl":"","callLlmUrl":"","callTtsUrl":"","callSystemPrompt":"","callGreeting":""},"success":true}},"CallOkResponse":{"description":"Success envelope of call controls that only confirm the action.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation.","properties":{"ok":{"type":"boolean","description":"Always `true` on success.","example":true}}}}}],"example":{"code":200,"data":{"ok":true},"success":true}},"CallRecordingStopResponse":{"description":"Success envelope of `POST /call/record/stop`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Recording result.","properties":{"ok":{"type":"boolean","description":"Always `true` on success.","example":true},"mediaKey":{"type":"string","description":"URL of the uploaded WAV (historical field name). Empty when no recording was active.","example":"https://my-bucket.s3.amazonaws.com/call-recordings/9b2f6a1e-4c1d-4e0b-8f7a-2d3c4b5a6e7f.wav"}}}}}],"example":{"code":200,"data":{"ok":true,"mediaKey":"https://my-bucket.s3.amazonaws.com/call-recordings/9b2f6a1e-4c1d-4e0b-8f7a-2d3c4b5a6e7f.wav"},"success":true}},"CallVideoStatsResponse":{"description":"Success envelope of `GET /call/{call_id}/video/stats`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Telemetry of the video socket attached to the call.","properties":{"callId":{"type":"string","description":"Engine call ID.","example":"call_17B3F2A1C9D04E8F"},"framing":{"type":"string","description":"Inbound framing the socket was opened with.","enum":["participant","single-stream"],"example":"participant"},"uptimeSeconds":{"type":"number","description":"Seconds since the video socket opened.","example":42.7},"inbound":{"type":"object","description":"Peer-to-client video counters.","properties":{"participants":{"type":"integer","description":"Frame queues on the socket, one per camera (1 in single-stream framing).","example":1},"framesReceived":{"type":"integer","description":"Access units received from WhatsApp and queued.","example":1260},"framesDelivered":{"type":"integer","description":"Access units written to the client.","example":1248},"framesShed":{"type":"integer","description":"Queued access units dropped under backpressure or flushed by a newer keyframe.","example":12},"participantsRejected":{"type":"integer","description":"Frames refused because the camera cap was reached.","example":0},"backlogBytes":{"type":"integer","description":"Bytes currently waiting to be written.","example":0},"peakBacklogBytes":{"type":"integer","description":"Largest backlog seen since the socket opened.","example":184320},"participantCap":{"type":"integer","description":"Maximum cameras demuxed on one socket.","example":32},"framesPerSecond":{"type":"number","description":"Average delivered frames per second since the socket opened. Omitted when uptime is zero.","example":29.2},"streams":{"type":"array","description":"Per-camera counters (participant framing only; empty in single-stream framing).","items":{"type":"object","description":"Counters of one camera.","properties":{"id":{"type":"string","description":"Participant ID used in the frame header.","example":"123456789012345@lid"},"frames":{"type":"integer","description":"Access units received from this camera.","example":1260},"bytes":{"type":"integer","description":"Bytes received from this camera.","example":5120344},"orientation":{"type":"integer","description":"Last known orientation (0-3).","example":0},"ssrc":{"type":"integer","description":"RTP SSRC of the camera stream.","example":3405691582},"secondsSinceLastFrame":{"type":"number","description":"Seconds since the last access unit from this camera.","example":0.03},"secondsActive":{"type":"number","description":"Seconds since the first access unit from this camera.","example":42.1},"fps":{"type":"number","description":"Average frames per second of this camera.","example":29.9}}}}}},"outbound":{"type":"object","description":"Client-to-peer video counters.","properties":{"framesSent":{"type":"integer","description":"Access units accepted and sent to WhatsApp.","example":1190},"bytesSent":{"type":"integer","description":"Bytes accepted and sent.","example":4388120},"framesDropped":{"type":"integer","description":"Access units dropped because the call had no video media yet.","example":35},"framesOversize":{"type":"integer","description":"Access units ignored for exceeding 1 MiB.","example":0},"keyframeRequests":{"type":"integer","description":"Keyframe requests received from the peer.","example":2},"mediaReady":{"type":"boolean","description":"Whether outbound video media is live.","example":true},"mediaReadyAfterSeconds":{"type":"number","description":"Seconds from socket open to the first accepted frame. Omitted until then.","example":1.8},"framesPerSecond":{"type":"number","description":"Average sent frames per second since the socket opened. Omitted when uptime is zero.","example":27.9}}}}}}}],"example":{"code":200,"data":{"callId":"call_17B3F2A1C9D04E8F","framing":"single-stream","uptimeSeconds":12.4,"inbound":{"participants":1,"framesReceived":360,"framesDelivered":360,"framesShed":0,"participantsRejected":0,"backlogBytes":0,"peakBacklogBytes":65536,"participantCap":32,"framesPerSecond":29,"streams":[]},"outbound":{"framesSent":0,"bytesSent":0,"framesDropped":0,"framesOversize":0,"keyframeRequests":0,"mediaReady":false,"framesPerSecond":0}},"success":true}},"CallParticipantsAddResponse":{"description":"Success envelope of `POST /call/participants/add`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Per-target invite result.","properties":{"ok":{"type":"boolean","description":"`true` only when every target was invited.","example":true},"failed":{"type":"array","description":"One `\"target: reason\"` entry per failed target; empty when all succeeded.","items":{"type":"string","description":"Failed target and the engine reason.","example":"123456789012347@lid: meowcaller: participant is already in the call roster"},"example":[]}}}}}],"example":{"code":200,"data":{"ok":true,"failed":[]},"success":true}},"CallLinkCreateResponse":{"description":"Success envelope of `POST /call/link/create`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CallLinkInfo"}}}],"example":{"code":200,"data":{"token":"Xk3pQ9aB7cD2eF4g","url":"https://call.whatsapp.com/video/Xk3pQ9aB7cD2eF4g","video":true},"success":true}},"CallLinkPreviewResponse":{"description":"Success envelope of `GET /call/link/preview`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CallLinkPreviewInfo"}}}],"example":{"code":200,"data":{"token":"Xk3pQ9aB7cD2eF4g","video":true,"approvalRequired":true,"isAdmin":false,"creator":"123456789012345@lid","creatorPhone":"5511988888888@s.whatsapp.net"},"success":true}},"CallHandResponse":{"description":"Success envelope of `POST /call/hand`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Applied hand state.","properties":{"ok":{"type":"boolean","description":"Always `true` on success.","example":true},"raised":{"type":"boolean","description":"Hand state that was applied.","example":true}}}}}],"example":{"code":200,"data":{"ok":true,"raised":true},"success":true}},"CallEnabledToggleResponse":{"description":"Success envelope of the call toggles that take `enabled` (`/call/video`, `/call/screenshare`, `/call/waiting-room/approval`).","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Applied toggle value.","properties":{"ok":{"type":"boolean","description":"Always `true` on success.","example":true},"enabled":{"type":"boolean","description":"Value that was applied (the default `true` when omitted).","example":true}}}}}],"example":{"code":200,"data":{"ok":true,"enabled":true},"success":true}},"CallGroupStateResponse":{"description":"Success envelope of `GET /call/{call_id}/group/state`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CallGroupState"}}}],"example":{"code":200,"data":{"callId":"call_5C1E9A7B3D2F4E60","transactionId":4,"participants":[{"jid":"123456789012345@lid","phone":"5511988888888@s.whatsapp.net","state":"connected"}]},"success":true}},"CallWaitingRoomResponse":{"description":"Success envelope of `GET /call/{call_id}/waiting-room`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CallWaitingRoomState"}}}],"example":{"code":200,"data":{"callId":"call_8D4B2E6A1C9F3E70","enabled":true,"isAdmin":true,"inWaitingRoom":false,"transactionId":2,"users":[]},"success":true}},"UserContactLinkResolveResponse":{"description":"Success envelope of `POST /user/contact-link/resolve`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Handler payload with its own success flag and the resolved target.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"data":{"type":"object","description":"Account the QR link points to.","properties":{"JID":{"type":"string","description":"JID of the account behind the link.","example":"5511999999999@s.whatsapp.net"},"Type":{"type":"string","description":"Link target type reported by WhatsApp, normally `contact`.","example":"contact"},"PushName":{"type":"string","description":"Display (push) name of the account. May be empty.","example":"Example Store"}}}}}}}]},"UserIdentityCodesResponse":{"description":"Success envelope of `GET /user/identity-code/{jid}`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Handler payload with its own success flag and the verification codes.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"data":{"type":"object","description":"Public identity verification values. No private keys are included.","properties":{"UserID":{"type":"string","description":"Contact LID the codes were generated for.","example":"123456789012345@lid"},"PhoneNumber":{"type":"string","description":"Contact phone JID when the LID-to-phone mapping is known, otherwise empty.","example":"5511999999999@s.whatsapp.net"},"Username":{"type":"string","description":"Contact username when known, otherwise empty.","example":"examplestore"},"NumericCode":{"type":"string","description":"60-digit security code, the same number shown in the WhatsApp app.","example":"123456789012345678901234567890123456789012345678901234567890"},"DisplayQRCode":{"type":"string","format":"byte","description":"Base64 payload of the QR code this account displays for scanning.","example":"AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJw=="},"VerificationQRCode":{"type":"string","format":"byte","description":"Base64 payload expected when scanning the contact's QR code.","example":"KCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4/QEFCQ0RFRkdISUpLTE1OTw=="}}}}}}}]},"UserUsernameResolveResponse":{"description":"Success envelope of `POST /user/username/resolve`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Handler payload with its own success flag and the resolution.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"data":{"type":"object","description":"Username resolution result.","properties":{"LID":{"type":"string","description":"LID of the username owner. Empty when `KeyRequired` is true.","example":"123456789012345@lid"},"Username":{"type":"string","description":"Canonical username without `@`. Empty when `KeyRequired` is true.","example":"examplestore"},"KeyRequired":{"type":"boolean","description":"`true` when the owner protects the username with a key and the request had no key or a wrong one.","example":false}}}}}}}]},"UserInfoRequest":{"type":"object","description":"Numbers or JIDs to look up. Provide `phone` (preferred) or the legacy `Phone`.","properties":{"phone":{"description":"One phone number/JID as a string, or several as an array. Read before `Phone`.","oneOf":[{"type":"string","description":"Single phone number with country code, or user JID.","example":"5511999999999"},{"type":"array","description":"Several phone numbers or user JIDs.","items":{"type":"string"},"example":["5511999999999","5511988888888"]}],"example":["5511999999999","5511988888888"]},"Phone":{"description":"Legacy spelling of `phone`, used only when `phone` is absent or has no string value.","oneOf":[{"type":"string","description":"Single phone number with country code, or user JID.","example":"5511999999999"},{"type":"array","description":"Several phone numbers or user JIDs.","items":{"type":"string"},"example":["5511999999999"]}],"example":["5511999999999@s.whatsapp.net"]}}},"UserInfoDevice":{"type":"object","description":"One device registered to the account.","properties":{"user":{"type":"string","description":"User part of the device JID.","example":"5511999999999"},"agent":{"type":"string","description":"Raw agent number of the device JID, as a string.","example":"0"},"device":{"type":"string","description":"Platform name derived from the device ID.","enum":["UNKNOWN","CHROME","FIREFOX","IE","OPERA","SAFARI","EDGE","DESKTOP","IPAD","ANDROID_TABLET","OHANA","ALOHA","CATALINA","TCL_TV"],"example":"SAFARI"},"server":{"type":"string","description":"JID server of the device.","example":"s.whatsapp.net"},"ad":{"type":"string","description":"Device address in `user.agent:device@server` form.","example":"5511999999999.0:5@s.whatsapp.net"},"jid":{"type":"string","description":"Device JID (`user:device@server`; device 0 has no suffix).","example":"5511999999999:5@s.whatsapp.net"}}},"UserInfoEntry":{"type":"object","description":"Profile data of one queried account.","properties":{"jid":{"type":"string","description":"Account JID.","example":"5511999999999@s.whatsapp.net"},"status":{"type":"string","description":"Status (about) text. Empty when hidden or not set.","example":"Available"},"picture_id":{"type":"string","description":"Current profile picture ID. Empty when there is no picture or it is hidden.","example":"1700000000"},"verified_name":{"type":"string","description":"Verified business name. Omitted for personal accounts.","example":"Example Store"},"business_name":{"type":"string","description":"Same value as `verified_name`, kept for compatibility. Omitted for personal accounts.","example":"Example Store"},"lid":{"type":"string","description":"Account LID when WhatsApp reports one. Omitted otherwise.","example":"123456789012345@lid"},"is_business_account":{"type":"boolean","description":"`true` when WhatsApp returned verified-name data for the account.","example":false},"device_count":{"type":"integer","description":"Number of devices registered to the account.","example":2},"first_device":{"type":"string","description":"JID of the first device in the list (usually the phone). Omitted when there are no devices.","example":"5511999999999@s.whatsapp.net"},"verified_level":{"type":"string","description":"Reserved for the business verification level. Currently never filled by this endpoint.","example":"high"},"verified_certificate":{"type":"object","description":"Present only for business accounts with a certificate.","properties":{"has_signature":{"type":"boolean","description":"`true` when the certificate carries a signature.","example":true},"has_server_signature":{"type":"boolean","description":"`true` when the certificate carries a WhatsApp server signature.","example":true}}},"devices":{"type":"array","description":"Devices registered to the account. `null` when WhatsApp lists none.","items":{"$ref":"#/components/schemas/UserInfoDevice"}}}},"UserInfoResponse":{"description":"Success envelope of `POST /user/info`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Lookup result.","properties":{"users":{"type":"object","description":"Profile data keyed by account JID.","additionalProperties":{"$ref":"#/components/schemas/UserInfoEntry"},"example":{"5511999999999@s.whatsapp.net":{"jid":"5511999999999@s.whatsapp.net","status":"Available","picture_id":"1700000000","is_business_account":false,"device_count":1,"first_device":"5511999999999@s.whatsapp.net","devices":[{"user":"5511999999999","agent":"0","device":"UNKNOWN","server":"s.whatsapp.net","ad":"5511999999999.0:0@s.whatsapp.net","jid":"5511999999999@s.whatsapp.net"}]}}}}}}}]},"UserCheckResponse":{"description":"Success envelope of `POST /user/check`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Check result.","properties":{"Users":{"type":"array","description":"One entry per queried number.","items":{"type":"object","description":"Registration data for one number.","properties":{"Query":{"type":"string","description":"The number as WhatsApp echoed it for this query.","example":"5511988888888"},"IsInWhatsapp":{"type":"boolean","description":"`true` when the number has a WhatsApp account.","example":true},"JID":{"type":"string","description":"Phone-shaped JID of the number, even when WhatsApp answers in LID addressing mode.","example":"5511988888888@s.whatsapp.net"},"LID":{"type":"string","description":"LID of the account, empty when WhatsApp reports none.","example":"123456789012346@lid"},"VerifiedName":{"type":"string","description":"Verified business name, empty for personal accounts.","example":"Example Store"},"Username":{"type":"string","description":"WhatsApp username. Omitted when not reported.","example":"examplestore"},"VerifiedLevel":{"type":"string","description":"Business verification level. Omitted for personal accounts.","example":"high"},"DisappearingMode":{"type":"object","description":"Default disappearing-message setting of the account. Omitted when not reported.","properties":{"enabled":{"type":"boolean","description":"`true` when a disappearing-message duration is set.","example":true},"duration_sec":{"type":"integer","format":"int64","description":"Duration in seconds; 0 when disabled.","example":604800},"set_at":{"type":"string","format":"date-time","description":"UTC time the setting was applied. Omitted when unknown.","example":"2026-07-01T12:34:56Z"}}}}}}}}}}]},"UserAvatarResponse":{"description":"Success envelope of `POST /user/avatar`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Profile picture metadata returned by WhatsApp.","properties":{"url":{"type":"string","description":"Temporary CDN URL of the image.","example":"https://pps.whatsapp.net/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"},"id":{"type":"string","description":"Picture ID; the same value as `picture_id` in `POST /user/info`.","example":"1700000000"},"type":{"type":"string","description":"`image` for the full picture or `preview` for the thumbnail.","enum":["image","preview"],"example":"preview"},"direct_path":{"type":"string","description":"CDN path of the image.","example":"/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"},"hash":{"type":"string","format":"byte","nullable":true,"description":"Base64 hash reported by WhatsApp; usually `null`.","example":null}}}}}]},"UserPhotoResponse":{"description":"Success envelope of `POST /user/photo`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Upload result.","properties":{"Details":{"type":"string","description":"Fixed confirmation message.","example":"Profile photo set successfully"},"PictureID":{"type":"string","description":"ID of the new profile picture.","example":"1757862000"}}}}}]},"UserPhotoRemoveResponse":{"description":"Success envelope of `POST /user/photo/remove`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Removal result.","properties":{"Details":{"type":"string","description":"Fixed confirmation message.","example":"Profile photo removed successfully"}}}}}]},"UserPresenceResponse":{"description":"Success envelope of `POST /user/presence`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Confirmation.","properties":{"Details":{"type":"string","description":"Fixed confirmation message (spelling as returned by the gateway).","example":"Presence set successfuly"}}}}}]},"UserPrivacySettingsResponse":{"description":"Success envelope of `GET /user/privacy/settings`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Privacy settings as reported by WhatsApp; empty string when not reported.","properties":{"group_add":{"type":"string","description":"Who can add you to groups.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"last_seen":{"type":"string","description":"Who can see your last seen.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"status":{"type":"string","description":"Who can see your status updates.","enum":["all","contacts","contact_blacklist","none",""],"example":"contacts"},"profile":{"type":"string","description":"Who can see your profile photo.","enum":["all","contacts","contact_blacklist","none",""],"example":"all"},"read_receipts":{"type":"string","description":"Whether read receipts are sent.","enum":["all","none",""],"example":"all"},"online":{"type":"string","description":"Who can see when you are online.","enum":["all","match_last_seen",""],"example":"match_last_seen"},"call_add":{"type":"string","description":"Who can call you (`known` silences unknown callers).","enum":["all","known",""],"example":"all"}}}}}]},"UserPushNameResponse":{"description":"Success envelope of `POST /user/pushname`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Update result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation message.","example":"Push name updated successfully"},"push_name":{"type":"string","description":"Push name that was set.","example":"Example Store"}}}}}]},"UserContactInfoRequest":{"type":"object","description":"Contact to inspect.","required":["phone"],"properties":{"phone":{"type":"string","description":"Phone number with country code, user JID or LID.","example":"5511999999999"}}},"UserContactInfoResponse":{"description":"Success envelope of `POST /user/contact/info`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Consolidated contact view. Sections are `null` when the source failed or does not apply.","properties":{"phone":{"type":"string","description":"Phone number (user part of the phone JID).","example":"5511988888888"},"jid":{"type":"string","description":"Phone-shaped JID of the contact.","example":"5511988888888@s.whatsapp.net"},"input_type":{"type":"string","description":"How the request `phone` was interpreted.","enum":["phone","jid","lid"],"example":"phone"},"lid":{"type":"string","nullable":true,"description":"Contact LID when known, otherwise `null`.","example":"123456789012346@lid"},"is_on_whatsapp":{"type":"boolean","description":"`true` when the number has a WhatsApp account.","example":true},"verified_name":{"type":"string","description":"Verified business name. Omitted for personal accounts.","example":"Example Store"},"user_info":{"type":"object","nullable":true,"description":"WhatsApp user info, or `null` when unavailable.","properties":{"status":{"type":"string","description":"Status (about) text.","example":"Open Monday to Friday"},"picture_id":{"type":"string","description":"Current profile picture ID; empty when none.","example":"1728656243"},"verified_name":{"type":"string","description":"Verified business name. Omitted for personal accounts.","example":"Example Store"},"is_business_account":{"type":"boolean","description":"`true` when verified-name data exists.","example":true},"device_count":{"type":"integer","description":"Number of registered devices.","example":1}}},"devices":{"type":"array","nullable":true,"description":"Registered devices, or `null` when unavailable.","items":{"$ref":"#/components/schemas/UserInfoDevice"}},"avatar":{"type":"object","nullable":true,"description":"Profile picture data, or `null` when there is no picture, it is hidden, or the lookup failed.","properties":{"url":{"type":"string","description":"Temporary CDN URL of the picture (full size, or the preview when only the preview was available).","example":"https://pps.whatsapp.net/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"},"id":{"type":"string","description":"Picture ID.","example":"1728656243"},"type":{"type":"string","description":"`image` or `preview`.","example":"image"},"direct_path":{"type":"string","description":"CDN path of the picture.","example":"/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"},"hash":{"type":"string","format":"byte","description":"Base64 hash reported by WhatsApp. Omitted when empty.","example":"3q2+7w=="},"base64":{"type":"string","description":"Picture downloaded by the gateway as a data URL. Omitted when the download failed.","example":"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2Q=="},"width":{"type":"integer","description":"Picture width in pixels. Omitted when unknown.","example":640},"height":{"type":"integer","description":"Picture height in pixels. Omitted when unknown.","example":640},"preview_url":{"type":"string","description":"Thumbnail URL. Present only when both full and preview lookups succeeded.","example":"https://pps.whatsapp.net/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?stp=dst-jpg_s96x96&ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"},"preview_direct_path":{"type":"string","description":"Thumbnail CDN path. Present only with `preview_url`.","example":"/v/t61.24694-24/123456789_1234567890123456_1234567890123456789_n.jpg?stp=dst-jpg_s96x96&ccb=11-4&oh=01_Q5AaIExample&oe=68E0A1B2"}}},"contact_names":{"type":"object","nullable":true,"description":"Names from the local contact store, or `null` when the contact is not stored.","properties":{"first_name":{"type":"string","description":"First name from the address book.","example":"Example"},"full_name":{"type":"string","description":"Full name from the address book.","example":"Example Store"},"push_name":{"type":"string","description":"Name the contact set for themselves.","example":"Example Store"},"business_name":{"type":"string","description":"Verified business name stored locally.","example":"Example Store"}}},"business_profile":{"type":"object","nullable":true,"description":"Business profile, or `null` for personal accounts and lookup failures.","properties":{"address":{"type":"string","description":"Business address.","example":"100 Example Avenue, Sao Paulo"},"email":{"type":"string","description":"Business email.","example":"contact@example.com"},"business_hours_timezone":{"type":"string","description":"IANA time zone of the business hours.","example":"America/Sao_Paulo"},"categories":{"type":"array","nullable":true,"description":"Business categories.","items":{"$ref":"#/components/schemas/UserBusinessCategory"}},"profile_options":{"type":"object","description":"Raw profile options reported by WhatsApp.","additionalProperties":{"type":"string"},"example":{"commerce_experience":"catalog"}},"business_hours":{"type":"array","nullable":true,"description":"Opening hours per weekday.","items":{"$ref":"#/components/schemas/UserBusinessHours"}}}}}}}}]},"UserBusinessCategory":{"type":"object","description":"One business category.","properties":{"id":{"type":"string","description":"Category ID.","example":"133436743388217"},"name":{"type":"string","description":"Category name in the language WhatsApp returned.","example":"Shopping & Retail"}}},"UserBusinessHours":{"type":"object","description":"Opening hours for one weekday.","properties":{"day_of_week":{"type":"string","description":"Three-letter weekday.","example":"mon"},"mode":{"type":"string","description":"Opening mode reported by WhatsApp, for example `specific_hours`, `open_24h` or `appointment_only`.","example":"specific_hours"},"open_time":{"type":"string","description":"Opening time as `HH:MM`; empty when the mode has no hours.","example":"09:00"},"close_time":{"type":"string","description":"Closing time as `HH:MM`; empty when the mode has no hours.","example":"18:00"}}},"UserContactAddRequest":{"type":"object","description":"Contact to save.","required":["phone","full_name"],"properties":{"phone":{"type":"string","description":"Phone number with country code or user JID.","example":"5511999999999"},"full_name":{"type":"string","description":"Name to save in the address book. Cannot be empty.","minLength":1,"example":"Maria Silva"}}},"UserContactAddResponse":{"description":"Success envelope of `POST /user/contact/add`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Save result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation message.","example":"Contact added successfully"},"phone":{"type":"string","description":"`phone` exactly as sent.","example":"5511999999999"},"full_name":{"type":"string","description":"Name that was saved.","example":"Maria Silva"}}}}}]},"UserContactRemoveRequest":{"type":"object","description":"Contact to remove.","required":["phone"],"properties":{"phone":{"type":"string","description":"Phone number with country code or user JID.","example":"5511999999999"}}},"UserContactRemoveResponse":{"description":"Success envelope of `POST /user/contact/remove`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Removal result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation message.","example":"Contact removed successfully"},"phone":{"type":"string","description":"`phone` exactly as sent.","example":"5511999999999"}}}}}]},"UserStatusGetResponse":{"description":"Success envelope of `GET /user/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Status text.","properties":{"status":{"type":"string","description":"Current about text; empty when not set.","example":"Available for support 9am-6pm"}}}}}]},"UserStatusSetResponse":{"description":"Success envelope of `POST /user/status`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Update result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Fixed confirmation message.","example":"Status updated successfully"},"status":{"type":"string","description":"Status text that was set.","example":"Available for support 9am-6pm"}}}}}]},"UserUpdateRequest":{"type":"object","description":"Gateway user fields to change. At least one must differ from the current value.","properties":{"name":{"type":"string","description":"New gateway user name, up to 255 characters.","maxLength":255,"example":"sales-team"},"token":{"type":"string","description":"New API token, at least 8 characters, unique across users.","minLength":8,"example":"9f8e7d6c5b4a3210fedcba98"}}},"UserUpdateResponse":{"description":"Success envelope of `POST /user/update`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Updated gateway user record.","properties":{"id":{"type":"string","description":"Gateway user ID.","example":"3f0b9f2c8e7d4a6b9c1d2e3f4a5b6c7d"},"name":{"type":"string","description":"Final user name.","example":"sales-team"},"token":{"type":"string","description":"Final API token (new or unchanged). Secret.","example":"9f8e7d6c5b4a3210fedcba98"},"message":{"type":"string","description":"Fixed confirmation message.","example":"Profile updated successfully"}}}}}]},"UserBusinessProfileResponse":{"description":"Success envelope of `POST /user/business/profile`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Business profile data.","properties":{"jid":{"type":"string","description":"Account JID.","example":"5511988888888@s.whatsapp.net"},"email":{"type":"string","description":"Business email; empty when not available.","example":"contact@example.com"},"address":{"type":"string","description":"Business address; empty when not available.","example":"100 Example Avenue, Sao Paulo"},"categories":{"type":"array","nullable":true,"description":"Business categories.","items":{"$ref":"#/components/schemas/UserBusinessCategory"}},"profile_options":{"type":"object","nullable":true,"description":"Raw profile options reported by WhatsApp.","additionalProperties":{"type":"string"},"example":{"commerce_experience":"catalog"}},"business_hours_timezone":{"type":"string","description":"IANA time zone of the business hours.","example":"America/Sao_Paulo"},"business_hours":{"type":"array","nullable":true,"description":"Opening hours per weekday.","items":{"$ref":"#/components/schemas/UserBusinessHours"}},"verified_name":{"type":"string","description":"Verified business name. Omitted when empty.","example":"Example Store"},"business_name":{"type":"string","description":"Declared in the response type but never filled by this endpoint (omitted).","example":"Example Store"},"status":{"type":"string","description":"Status (about) text. Omitted when empty.","example":"Open Monday to Friday"},"picture_id":{"type":"string","description":"Profile picture ID. Omitted when empty.","example":"1728656243"},"is_business_account":{"type":"boolean","description":"`true` when a verified name or a business profile was found.","example":true},"profile_data_available":{"type":"boolean","description":"`true` when the business profile fields were read successfully.","example":true}}}}}]},"UserContactsResponse":{"description":"Success envelope of `GET /user/contacts`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Contacts keyed by JID.","additionalProperties":{"type":"object","description":"Names stored for one contact.","properties":{"Found":{"type":"boolean","description":"Always `true` for listed contacts.","example":true},"FirstName":{"type":"string","description":"First name from the address book.","example":"Maria"},"FullName":{"type":"string","description":"Full name from the address book.","example":"Maria Silva"},"PushName":{"type":"string","description":"Name the contact set for themselves.","example":"Maria"},"BusinessName":{"type":"string","description":"Verified business name.","example":"Example Store"},"Username":{"type":"string","description":"WhatsApp username when known.","example":"examplestore"},"RedactedPhone":{"type":"string","description":"Masked phone number, only for LID members seen in groups.","example":"+55∙∙∙∙∙∙∙∙88"}}},"example":{"5511999999999@s.whatsapp.net":{"Found":true,"FirstName":"Maria","FullName":"Maria Silva","PushName":"Maria","BusinessName":"","Username":"","RedactedPhone":""}}}}}]},"UserLIDGetResponse":{"description":"Success envelope of `GET|POST /user/lid/get`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Lookup result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"phone":{"type":"string","description":"Phone JID parsed from the input.","example":"5511999999999@s.whatsapp.net"},"lid":{"type":"string","description":"Mapped LID; empty when `has_lid` is false.","example":"123456789012345@lid"},"has_lid":{"type":"boolean","description":"`true` when the local store has a LID for this number.","example":true}}}}}]},"UserJIDFromLIDResponse":{"description":"Success envelope of `GET|POST /user/lid/from-lid`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Lookup result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"lid":{"type":"string","description":"LID parsed from the input.","example":"123456789012345@lid"},"phone":{"type":"string","description":"Phone JID mapped to the LID.","example":"5511999999999@s.whatsapp.net"}}}}}]},"DeviceUsersResponse":{"description":"Success envelope of `POST /device/users`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Device list.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"devices":{"type":"array","nullable":true,"description":"Devices of all requested accounts; `null` when none were found.","items":{"$ref":"#/components/schemas/DeviceInfo"}},"count":{"type":"integer","description":"Number of devices returned.","example":3}}}}}]},"DeviceUsersContextRequest":{"type":"object","description":"Accounts whose devices are listed, with an optional timeout and tag.","required":["user_jids"],"properties":{"user_jids":{"type":"array","description":"Phone numbers with country code, phone JIDs or LIDs. At least one item.","minItems":1,"items":{"type":"string","description":"Phone number, phone JID or LID.","example":"5511999999999@s.whatsapp.net"},"example":["5511999999999@s.whatsapp.net"]},"context":{"type":"string","description":"Free-text tag echoed in the response and logs.","example":"crm-sync"},"timeout":{"type":"integer","format":"int64","default":30000000000,"description":"Query timeout in nanoseconds (Go `time.Duration`). `0` or omitted means 30 seconds.","example":10000000000}}},"DeviceUsersContextResponse":{"description":"Success envelope of `POST /device/users/context`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Device list and echoed tag.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"devices":{"type":"array","nullable":true,"description":"Devices of all requested accounts; `null` when none were found.","items":{"$ref":"#/components/schemas/DeviceInfo"}},"count":{"type":"integer","description":"Number of devices returned.","example":2},"context":{"type":"string","description":"The request `context`, or an empty string.","example":"crm-sync"}}}}}]},"PrivacySetSettingResponse":{"description":"Success envelope of `POST /privacy/settings`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Change result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Confirmation built from the request values.","example":"Privacy setting last_seen updated to contacts"},"setting":{"type":"string","description":"`setting` exactly as sent.","example":"last_seen"},"value":{"type":"string","description":"`value` exactly as sent.","example":"contacts"}}}}}]},"PrivacyDisappearingTimerResponse":{"description":"Success envelope of `POST /privacy/disappearing-timer`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Update result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200.","example":true},"message":{"type":"string","description":"Confirmation built from the request value.","example":"Default disappearing timer set to 7d"},"timer":{"type":"string","description":"`timer` exactly as sent.","example":"7d"}}}}}]},"PrivacyBlocklistUpdateResponse":{"description":"Success envelope of `POST /privacy/blocklist`.","allOf":[{"$ref":"#/components/schemas/SuccessEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Update result.","properties":{"success":{"type":"boolean","description":"Always `true` on 200, even when some contacts failed.","example":true},"message":{"type":"string","description":"Confirmation counting every requested contact.","example":"Successfully blocked 2 contact(s)"},"action":{"type":"string","description":"`action` exactly as sent.","example":"block"},"users":{"type":"array","description":"`users` exactly as sent.","items":{"type":"string"},"example":["5511977777777","5511966666666@s.whatsapp.net"]}}}}}]},"GroupHistorySendFailureResponse":{"description":"502 body of `POST /group/history/send`. Legacy envelope: top-level `success` stays `true`; `data.success` is `false` and `data.error` carries the fixed do-not-retry hint.","allOf":[{"$ref":"#/components/schemas/LegacyErrorEnvelope"},{"type":"object","properties":{"data":{"type":"object","description":"Outcome of the history send.","properties":{"success":{"type":"boolean","description":"`true` only when both messages were acknowledged. `false` on 502.","example":true},"error":{"type":"string","description":"Present only on 502. Fixed hint that the IDs must not be retried.","example":"history operation failed or remains unconfirmed; do not retry reserved IDs"},"result":{"$ref":"#/components/schemas/GroupHistorySendResult"},"retry_safe":{"type":"boolean","description":"Always `false`. The reserved IDs can never be reused.","example":false},"recipient_delivery_verified":{"type":"boolean","description":"Always `false`. Server acknowledgements do not prove recipient delivery.","example":false},"evidence_persisted":{"type":"boolean","description":"`true` when the terminal state of the reservation was stored.","example":true}}}}}]},"ErrorEnvelope":{"type":"object","description":"Error envelope written by the gateway for failed requests.","required":["code","error","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":400},"error":{"type":"string","description":"Human-readable error message.","example":"missing Phone in Payload"},"success":{"type":"boolean","description":"Always false for errors.","example":false}}},"SendMessageResult":{"type":"object","description":"Result of a successful send.","properties":{"Details":{"type":"string","description":"Always `Sent` for regular sends.","example":"Sent"},"Id":{"type":"string","description":"WhatsApp message ID (the custom `Id` when provided, otherwise generated).","example":"3EB0C767D26A1D6B8A9F"},"Timestamp":{"type":"string","description":"Server acknowledgement time.","format":"date-time","example":"2026-09-15T10:30:00-03:00"}}},"SendLinkResult":{"type":"object","description":"Result of a successful `/chat/send/link`.","properties":{"Details":{"type":"string","description":"Always `Link message sent successfully`.","example":"Link message sent successfully"},"Id":{"type":"string","description":"WhatsApp message ID (the custom `Id` when provided, otherwise generated).","example":"3EB0C767D26A1D6B8A9F"},"Timestamp":{"type":"string","description":"Server acknowledgement time.","format":"date-time","example":"2026-09-22T12:49:08-03:00"},"Link":{"type":"string","description":"The `Link` from the request.","example":"https://example.com/promo"},"Metadata":{"type":"object","description":"Preview metadata used for the card. Empty strings when the preview is disabled or nothing could be resolved.","properties":{"Title":{"type":"string","description":"Title sent on the card. When an image is sent without a title this is the fallback domain of the effective match (`matched_text` URL, else `Link`).","example":"example.com"},"Description":{"type":"string","description":"Description sent on the card (empty when none).","example":"Use code SAVE50 at checkout"},"Image":{"type":"string","description":"Image URL from the scraped metadata or `Preview.image` when it is an http(s) URL; the placeholder `data:image/jpeg;base64,...` when a base64 image was sent; empty when there is no image.","example":"https://example.com/promo.jpg"},"MatchedText":{"type":"string","description":"Text WhatsApp highlights as the link (`Preview.matched_text` when it is an http(s) URL found literally in the body, otherwise `Link`).","example":"https://example.com/promo"},"PreviewType":{"type":"string","description":"Wire preview type (`NONE` for image cards, `VIDEO`, `PLACEHOLDER`); empty when the preview is disabled or no preview was applied.","example":"NONE"},"PreviewMode":{"type":"string","description":"How the metadata was produced.","enum":["fetch","replace","merge","disabled"],"example":"replace"}}}}},"BusinessOrderRecoveryBody":{"type":"object","x-raw-error-body":true,"description":"Recovery body written WITHOUT the gateway envelope (no `code`) when an order was registered but the message could not be built or delivered. Keep `registered_order` and never retry as a new order.","properties":{"success":{"type":"boolean","description":"Always false.","example":false},"order_created":{"type":"boolean","description":"True when this request registered the order.","example":true},"order_reused":{"type":"boolean","description":"True when an existing order was being resent.","example":false},"order_exists":{"type":"boolean","description":"True when a registered order with ID and token exists.","example":true},"message_sent":{"type":"boolean","description":"False when no send was attempted; null when delivery is unknown.","nullable":true},"message_delivery":{"type":"string","description":"`not_attempted` or `unknown`.","enum":["unknown","not_attempted"],"example":"unknown"},"error":{"type":"string","description":"Failure phase.","enum":["order_creation_failed","order_created_message_build_failed","order_created_message_send_failed"],"example":"order_created_message_send_failed"},"registered_order":{"description":"Server-issued order to recover with `resend_registered_order`.","allOf":[{"$ref":"#/components/schemas/whatsmeow.BusinessCreatedOrder"}]}}},"BusinessOrderSendResult":{"type":"object","description":"Order message result.","properties":{"success":{"type":"boolean","description":"Always true on success.","example":true},"message":{"type":"string","description":"Fixed confirmation text.","example":"Order sent successfully"},"business_jid":{"type":"string","description":"Seller chat the order was sent to.","example":"5511988888888@s.whatsapp.net"},"message_id":{"type":"string","description":"WhatsApp message ID.","example":"3EB0C767D26A1D6B8A9F"},"timestamp":{"type":"string","description":"Server acknowledgement time.","format":"date-time","example":"2026-09-15T12:00:00Z"},"order_created":{"type":"boolean","description":"True only when this request registered a new order (`create_order`).","example":true},"order_reused":{"type":"boolean","description":"True when an existing registered order was resent.","example":false},"order_kind":{"type":"string","description":"`legacy_summary` or `registered_order`.","enum":["legacy_summary","registered_order"],"example":"registered_order"},"registered_order":{"type":"object","description":"Server-issued order (registered orders only).","properties":{"order_id":{"type":"string","description":"Order ID.","example":"1976123456789012"},"token":{"type":"string","description":"Order token; keep it to recover or resend the order.","example":"AR6example0rderT0kenBase64=="},"price":{"type":"object","description":"Server-issued totals.","properties":{"subtotal_amount":{"type":"string","description":"Subtotal in thousandths.","example":"3000000"},"total_amount":{"type":"string","description":"Total in thousandths.","example":"3000000"},"currency":{"type":"string","description":"Currency.","example":"BRL"},"price_status":{"type":"string","description":"Price status.","example":"PROVIDED"}}}}},"order_details":{"type":"object","description":"Summary of what was sent.","properties":{"item_count":{"type":"integer","description":"Number of order lines sent.","example":1},"order_id":{"type":"string","description":"Order ID (empty for legacy summaries without `order_id`).","example":"1976123456789012"}}}}},"BusinessLegacyProduct":{"type":"object","description":"Product in the compact shape used by `GET /business/catalog/{businessJID}` and `GET /business/products/{businessJID}`.","properties":{"id":{"type":"string","description":"Catalog product ID.","example":"7123456789012345"},"retailer_id":{"type":"string","description":"Retailer ID, when set.","example":"CHAIR-001"},"name":{"type":"string","description":"Product name.","example":"Wooden chair"},"description":{"type":"string","description":"Product description, when set.","example":"Solid wood chair with natural finish."},"price":{"type":"integer","nullable":true,"description":"Price as a JSON number holding the upstream thousandths value unchanged (`3000000` = 3,000.00); `null` when the upstream product has no usable price.","example":3000000},"currency":{"type":"string","description":"ISO-4217 currency.","example":"BRL"},"image_urls":{"type":"array","description":"Image URLs (original, or resized when no original is available).","items":{"type":"string"},"example":["https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"]},"availability":{"type":"string","description":"Availability label, when reported.","example":"in stock"}}},"BusinessEmptyRequest":{"type":"object","additionalProperties":false,"description":"Empty JSON object. No properties are accepted.","example":{}},"BusinessCollectionMutationResult":{"type":"object","description":"Identifier and review status of a created or edited collection.","properties":{"id":{"type":"string","description":"Collection ID. Edits return a NEW ID; use it from then on.","example":"7123456789012350"},"review_status":{"type":"string","description":"Meta review status as returned by the server (observed: `STATUS_APPROVED`).","example":"STATUS_APPROVED"}},"example":{"id":"7123456789012350","review_status":"STATUS_APPROVED"}},"BusinessCatalogProduct":{"type":"object","description":"Catalog product as returned by WhatsApp (typed business routes). Prices are strings holding integer thousandths of the currency.","properties":{"id":{"type":"string","description":"Catalog product ID.","example":"7123456789012345"},"retailer_id":{"type":"string","description":"Seller SKU / retailer ID, when set.","example":"CHAIR-001"},"belongs_to":{"type":"string","description":"Owner reference reported by the server, when present.","example":"5511988888888@s.whatsapp.net"},"name":{"type":"string","description":"Product name.","example":"Wooden chair"},"description":{"type":"string","description":"Product description.","example":"Solid wood chair with natural finish."},"price":{"type":"string","description":"Price in thousandths of the currency (`\"3000000\"` = 3,000.00).","example":"3000000"},"currency":{"type":"string","description":"ISO-4217 currency code.","example":"BRL"},"url":{"type":"string","description":"Product web page. The server normalizes it with a trailing slash.","example":"https://example.com/products/chair/"},"shimmed_url":{"type":"string","description":"Tracking-safe redirect URL generated by WhatsApp, when present.","example":"https://l.wl.co/l?u=https%3A%2F%2Fexample.com%2Fproducts%2Fchair%2F"},"is_hidden":{"type":"boolean","description":"True when the product is hidden from public catalog reads.","example":false},"is_sanctioned":{"type":"boolean","description":"True when Meta restricted the product.","example":false},"max_available":{"type":"integer","description":"Maximum orderable quantity, when reported.","example":10},"product_availability":{"type":"string","description":"Availability label reported by the server.","example":"in stock"},"compliance_category":{"type":"string","description":"Compliance category, e.g. `COUNTRY_ORIGIN_EXEMPT`.","example":"COUNTRY_ORIGIN_EXEMPT"},"compliance_info":{"description":"Country of origin and importer data, when set.","allOf":[{"$ref":"#/components/schemas/types.BusinessComplianceInfo"}]},"media":{"type":"object","description":"Product photos and videos.","properties":{"images":{"type":"array","description":"Photos; the first one is the main photo.","items":{"type":"object","properties":{"id":{"type":"string","description":"Media ID.","example":"7123456789012346"},"original_image_url":{"type":"string","description":"Full-size image URL.","example":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"},"request_image_url":{"type":"string","description":"Resized image URL (width/height of the request).","example":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}}}},"videos":{"type":"array","description":"Videos, when present.","items":{"type":"object","properties":{"id":{"type":"string","description":"Media ID.","example":"7123456789012349"},"original_video_url":{"type":"string","description":"Video URL.","example":"https://mmg.whatsapp.net/v/t42.1790-2/example-video.mp4"},"thumbnail_url":{"type":"string","description":"Video thumbnail URL.","example":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}}}}}},"sale_price":{"type":"object","description":"Sale price, when set.","properties":{"price":{"type":"string","description":"Sale price in thousandths of the currency.","example":"2499900"},"start_date":{"type":"string","description":"Sale start, when scheduled.","example":"2026-09-01"},"end_date":{"type":"string","description":"Sale end, when scheduled.","example":"2026-09-30"}}},"status_info":{"type":"object","description":"Meta review state.","properties":{"status":{"type":"string","description":"Review status: `NO_REVIEW`, `PENDING`, `APPROVED` or `REJECTED`.","example":"APPROVED"},"can_appeal":{"type":"boolean","description":"True when a rejected product can be appealed.","example":false}}},"variant_info":{"type":"object","additionalProperties":true,"description":"Variant availability, listing details, types and properties, when the product has variants.","example":{"types":[{"name":"Color","options":[{"value":"Natural"}]}]}}},"example":{"id":"7123456789012345","retailer_id":"CHAIR-001","name":"Wooden chair","description":"Solid wood chair with natural finish.","price":"3000000","currency":"BRL","url":"https://example.com/products/chair/","is_hidden":false,"is_sanctioned":false,"product_availability":"in stock","compliance_info":{"country_code_origin":"BR"},"media":{"images":[{"id":"7123456789012346","original_image_url":"https://mmg.whatsapp.net/v/t45.5328-4/example-chair.jpg?ccb=11-4&oh=01_Q5AaIexample&oe=66E6B2C0"}]},"sale_price":{"price":"2499900"},"status_info":{"status":"APPROVED"}}},"SuccessEnvelope":{"type":"object","description":"Success envelope written by the gateway (`s.Respond`) for 2xx responses. Compose it with `allOf` and override `data` with the operation-specific payload schema.","required":["code","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":200},"data":{"description":"Operation-specific result. JSON strings produced by the handler are decoded into objects or arrays before being written."},"success":{"type":"boolean","description":"Always true for 2xx responses.","example":true}}},"LegacyErrorEnvelope":{"type":"object","description":"Legacy error envelope kept for backward compatibility: some handlers write the error in `data` (a string, or an object carrying `message` or `error`) and report `success: true` even though the HTTP status is an error. Clients must check the HTTP status code.","x-legacy-envelope":true,"required":["code","data","success"],"properties":{"code":{"type":"integer","description":"HTTP status code repeated in the body.","example":404},"data":{"description":"Error written by the handler: a plain message string or an object carrying `message` or `error`.","oneOf":[{"type":"string","description":"Error message.","example":"Client not found"},{"type":"object","description":"Error object (for example newsletter, passkey and group history handlers). Carries `message` or `error`; other keys depend on the route.","additionalProperties":true,"properties":{"success":{"type":"boolean","description":"False inside the error object, when present.","example":false},"message":{"type":"string","description":"Error message, when the handler uses `message`.","example":"newsletter not found"},"error":{"type":"string","description":"Error code or message, when the handler uses `error`.","example":"not_connected"},"reason":{"type":"string","description":"Human-readable reason, when present.","example":"session is not connected"}}}],"example":"Client not found"},"success":{"type":"boolean","description":"Legacy: true even on error for these routes. Use the HTTP status code instead.","example":true}}},"PublicApiError":{"type":"object","additionalProperties":false,"required":["code"],"description":"Erro respondido pela própria API pública, antes de chegar à instância.","properties":{"code":{"type":"string","description":"Código estável do erro (ex.: `ACCOUNT_DEACTIVATED`)."},"message":{"type":"string","description":"Explicação legível, presente em alguns códigos."}}}},"responses":{"PublicApiUnauthorized":{"description":"Token ausente, inválido ou não reconhecido pela API.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"UNAUTHORIZED":{"summary":"Token não aceito","value":{"code":"UNAUTHORIZED"}}}}}},"PublicApiInstanceAccessDenied":{"description":"A instância está atribuída a uma conta (ou Revenda) desativada no painel. Desativar ou reativar a conta reflete na API em até 30 s.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"ACCOUNT_DEACTIVATED":{"summary":"Conta dona desativada","value":{"code":"ACCOUNT_DEACTIVATED","message":"A conta dona desta instância está desativada no painel."}}}}}},"PublicApiPayloadTooLarge":{"description":"Corpo da requisição (ou `Content-Length` declarado) acima do limite aceito pela API (32 MiB).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"PAYLOAD_TOO_LARGE":{"summary":"Corpo grande demais","value":{"code":"PAYLOAD_TOO_LARGE"}}}}}},"PublicApiRateLimited":{"description":"Limite de requisições por token atingido; aguarde o tempo do cabeçalho `Retry-After`.","headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"RATE_LIMITED":{"summary":"Muitas requisições","value":{"code":"RATE_LIMITED"}}}}}},"PublicApiUnavailable":{"description":"Não foi possível verificar o acesso da instância agora, ou a API está sobrecarregada; tente de novo após o `Retry-After`.","headers":{"Retry-After":{"description":"Segundos a esperar antes de tentar de novo.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"ACCESS_CHECK_UNAVAILABLE":{"summary":"Verificação de acesso indisponível","value":{"code":"ACCESS_CHECK_UNAVAILABLE"}},"OVERLOADED":{"summary":"API sobrecarregada","value":{"code":"OVERLOADED"}}}}}},"PublicApiWebSocketNotSupported":{"description":"Stream WebSocket não suportado pela URL base pública.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicApiError"},"examples":{"WEBSOCKET_NOT_SUPPORTED":{"summary":"WebSocket não suportado","value":{"code":"WEBSOCKET_NOT_SUPPORTED","message":"Streams WebSocket de chamada não são suportados pela URL base pública."}}}}}}}},"security":[{"ApiKeyAuth":[]}]}