{
  "openapi": "3.0.3",
  "info": {
    "title": "WaSMS Public API",
    "version": "1.2.0",
    "description": "Send and read WhatsApp, SMS and email messages and manage contacts, templates, lead forms and web chat for one organization.\n\n**Authentication.** Create an API key in the dashboard (API keys) and send it as `Authorization: Bearer wasms_...`. Systems that cannot send a header may put it in the query string as `secret=wasms_...`. A key belongs to one organization and only ever reads or changes that organization's data.\n\n**Scopes.** Every route names the scope it needs (`x-scope`). A key without it gets `403 INSUFFICIENT_SCOPE`.\n\n**Answers.** JSON, in one envelope: `{\"success\": true, \"data\": ...}` on success (lists add `total`, `page`, `per_page`), `{\"success\": false, \"error\": \"CODE\", \"code\": \"CODE\", \"message\": \"...\"}` on failure. The two exceptions are marked on the routes: GET /whatsapp/qr and GET /whatsapp/status answer the gateway's own JSON.\n\n**Rate limits.** Every API key has a limit of requests per minute, set on the key in the dashboard (60 unless changed). The count restarts at the start of each minute and covers every request made with the key, to this API and to the MCP endpoint together. Every answer carries `X-RateLimit-Limit` and `X-RateLimit-Remaining`. One request too many answers `429 RATE_LIMITED` with `Retry-After` (seconds until the next minute). In addition the web chat routes (/chat-widgets and /conversations) share 300 requests per minute per organization. Monthly plan limits apply to sending and answer `403 PLAN_LIMIT`.\n\n**Phone numbers** are digits with the country code; a leading `+` is accepted and removed.\n\n**Webhooks** (events sent to your server) are set up in the dashboard under Webhooks."
  },
  "servers": [
    {
      "url": "https://wasms.net/api/public/v1"
    }
  ],
  "tags": [
    {
      "name": "WhatsApp"
    },
    {
      "name": "Messages"
    },
    {
      "name": "SMS"
    },
    {
      "name": "Email"
    },
    {
      "name": "OTP"
    },
    {
      "name": "Contacts"
    },
    {
      "name": "Quick replies"
    },
    {
      "name": "Templates"
    },
    {
      "name": "Lead forms"
    },
    {
      "name": "Campaigns"
    },
    {
      "name": "Web chat"
    },
    {
      "name": "Gateway app"
    },
    {
      "name": "Learn"
    },
    {
      "name": "Meta"
    }
  ],
  "paths": {
    "/whatsapp/send": {
      "post": {
        "operationId": "post_whatsapp_send",
        "summary": "Send a WhatsApp message",
        "tags": [
          "WhatsApp"
        ],
        "description": "Sends one WhatsApp message, text or media, and waits for the gateway to accept it. If the organization's plan has a message signature it is appended to the text. The message is not added to the organization's conversations and produces no `message.sent` webhook (its `message.status` webhooks, delivered and read, do fire). The answer's `id` identifies the message for its delivered and read status (GET /messages/{id}, or the `message.status` webhook).\n\nScope: `messages:send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "message": {
                    "type": "string",
                    "description": "The text. With media_url it is the caption and may be empty."
                  },
                  "media_url": {
                    "type": "string",
                    "description": "Public https address of a file. When set, the message is sent as media."
                  },
                  "media_type": {
                    "type": "string",
                    "enum": [
                      "image",
                      "video",
                      "audio",
                      "document"
                    ],
                    "description": "Default: guessed from the file extension of media_url; document when unknown."
                  },
                  "filename": {
                    "type": "string",
                    "description": "Shown in WhatsApp for documents."
                  },
                  "mime_type": {
                    "type": "string",
                    "description": "Accepted and ignored."
                  },
                  "whatsapp_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Which of the organization's WhatsApp numbers to send from (id from GET /whatsapp/accounts). Default: the first connected number."
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Older name of whatsapp_id. whatsapp_id wins when both are sent."
                  },
                  "account_phone": {
                    "type": "string",
                    "description": "The sending number itself, instead of its id. Used only when no id is sent."
                  }
                },
                "required": [
                  "to"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "to": {
                          "type": "string",
                          "description": "Recipient, digits only"
                        },
                        "whatsapp_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "account_phone": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string",
                          "description": "text, or the media type"
                        },
                        "message_id": {
                          "type": "string",
                          "description": "The WhatsApp message id. Absent when the gateway did not report one."
                        },
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Id of this send. Ask GET /messages/{id} for its status with it; the message.status webhooks of this message carry it as data.message.id. Absent only when the gateway reported no message id."
                        }
                      },
                      "required": [
                        "sent",
                        "to",
                        "whatsapp_id",
                        "account_phone",
                        "type"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` (no `to`, or neither `message` nor `media_url`) or `INVALID_ACCOUNT_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_CONNECTED_ACCOUNT`: the organization has no connected WhatsApp number (or not the one asked for).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "get": {
        "operationId": "get_whatsapp_send",
        "summary": "Send a WhatsApp text message with a GET request",
        "tags": [
          "WhatsApp"
        ],
        "description": "For systems that can only call an address (SMS-gateway style templates). Text only. Put the key in `secret` when no header can be sent. The answer's `id` identifies the message for its delivered and read status (GET /messages/{id}, or the `message.status` webhook).\n\nScope: `messages:send`.",
        "parameters": [
          {
            "name": "recipient",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Recipient phone. `to` and `phone` are accepted as other names; one of the three is required."
          },
          {
            "name": "to",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "phone",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "message",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "account",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Sending WhatsApp number id. `account_id` and `whatsapp_id` are accepted as other names."
          },
          {
            "name": "account_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "whatsapp_id",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "to": {
                          "type": "string",
                          "description": "Recipient, digits only"
                        },
                        "whatsapp_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "account_phone": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string",
                          "description": "text, or the media type"
                        },
                        "message_id": {
                          "type": "string",
                          "description": "The WhatsApp message id. Absent when the gateway did not report one."
                        },
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Id of this send. Ask GET /messages/{id} for its status with it; the message.status webhooks of this message carry it as data.message.id. Absent only when the gateway reported no message id."
                        }
                      },
                      "required": [
                        "sent",
                        "to",
                        "whatsapp_id",
                        "account_phone",
                        "type"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_QUERY` (no recipient or no message) or `INVALID_ACCOUNT_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_CONNECTED_ACCOUNT`: the organization has no connected WhatsApp number (or not the one asked for).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/send": {
      "post": {
        "operationId": "post_send",
        "summary": "Send a WhatsApp message (old path)",
        "tags": [
          "WhatsApp"
        ],
        "description": "Same as POST /whatsapp/send. Kept so existing integrations keep working. The answer's `id` identifies the message for its delivered and read status (GET /messages/{id}, or the `message.status` webhook).\n\nScope: `messages:send`.",
        "deprecated": true,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "message": {
                    "type": "string",
                    "description": "The text. With media_url it is the caption and may be empty."
                  },
                  "media_url": {
                    "type": "string",
                    "description": "Public https address of a file. When set, the message is sent as media."
                  },
                  "media_type": {
                    "type": "string",
                    "enum": [
                      "image",
                      "video",
                      "audio",
                      "document"
                    ],
                    "description": "Default: guessed from the file extension of media_url; document when unknown."
                  },
                  "filename": {
                    "type": "string",
                    "description": "Shown in WhatsApp for documents."
                  },
                  "mime_type": {
                    "type": "string",
                    "description": "Accepted and ignored."
                  },
                  "whatsapp_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Which of the organization's WhatsApp numbers to send from (id from GET /whatsapp/accounts). Default: the first connected number."
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Older name of whatsapp_id. whatsapp_id wins when both are sent."
                  },
                  "account_phone": {
                    "type": "string",
                    "description": "The sending number itself, instead of its id. Used only when no id is sent."
                  }
                },
                "required": [
                  "to"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "to": {
                          "type": "string",
                          "description": "Recipient, digits only"
                        },
                        "whatsapp_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "account_phone": {
                          "type": "string"
                        },
                        "type": {
                          "type": "string",
                          "description": "text, or the media type"
                        },
                        "message_id": {
                          "type": "string",
                          "description": "The WhatsApp message id. Absent when the gateway did not report one."
                        },
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Id of this send. Ask GET /messages/{id} for its status with it; the message.status webhooks of this message carry it as data.message.id. Absent only when the gateway reported no message id."
                        }
                      },
                      "required": [
                        "sent",
                        "to",
                        "whatsapp_id",
                        "account_phone",
                        "type"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` (no `to`, or neither `message` nor `media_url`) or `INVALID_ACCOUNT_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_CONNECTED_ACCOUNT`: the organization has no connected WhatsApp number (or not the one asked for).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/whatsapp/poll": {
      "post": {
        "operationId": "post_whatsapp_poll",
        "summary": "Send a WhatsApp poll",
        "tags": [
          "WhatsApp"
        ],
        "description": "Sends a poll. The recipient's choice comes back as a normal inbound message. The answer's `id` identifies the message for its delivered and read status (GET /messages/{id}, or the `message.status` webhook).\n\nScope: `messages:send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "question": {
                    "type": "string"
                  },
                  "options": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "2 to 12 options"
                  },
                  "multiple_select": {
                    "type": "boolean",
                    "description": "Let the recipient pick more than one. Default false."
                  },
                  "whatsapp_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Which of the organization's WhatsApp numbers to send from (id from GET /whatsapp/accounts). Default: the first connected number."
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Older name of whatsapp_id. whatsapp_id wins when both are sent."
                  },
                  "account_phone": {
                    "type": "string",
                    "description": "The sending number itself, instead of its id. Used only when no id is sent."
                  }
                },
                "required": [
                  "to",
                  "question",
                  "options"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "to": {
                          "type": "string"
                        },
                        "whatsapp_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "account_phone": {
                          "type": "string"
                        },
                        "gateway_msg_id": {
                          "type": "string",
                          "description": "The WhatsApp message id; empty when not reported"
                        },
                        "options": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Id of this send. Ask GET /messages/{id} for its status with it; the message.status webhooks of this message carry it as data.message.id. Absent only when the gateway reported no message id."
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`, `TOO_MANY_OPTIONS` (more than 12) or `INVALID_ACCOUNT_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_CONNECTED_ACCOUNT`: the organization has no connected WhatsApp number (or not the one asked for).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/whatsapp/bulk": {
      "post": {
        "operationId": "post_whatsapp_bulk",
        "summary": "Send up to 1,000 WhatsApp messages",
        "tags": [
          "WhatsApp"
        ],
        "description": "Sends the messages one after another **inside this request** and answers when all are done, so the request lasts about `messages x throttle_ms`. Use a client timeout to match, or send smaller batches. A row that fails does not stop the rest; the answer is 200 with one result per row.\n\nScope: `messages:send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Default sending number for every row"
                  },
                  "throttle_ms": {
                    "type": "integer",
                    "default": 500,
                    "minimum": 100,
                    "maximum": 10000,
                    "description": "Pause between sends"
                  },
                  "messages": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "to": {
                          "type": "string",
                          "description": "Phone number with country code. A leading + is accepted and removed."
                        },
                        "message": {
                          "type": "string"
                        },
                        "account_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Sending number for this row; overrides the top-level account_id"
                        },
                        "media_url": {
                          "type": "string"
                        },
                        "media_type": {
                          "type": "string",
                          "enum": [
                            "image",
                            "video",
                            "audio",
                            "document"
                          ]
                        },
                        "filename": {
                          "type": "string"
                        },
                        "mime_type": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "to"
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 1000
                  }
                },
                "required": [
                  "messages"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "200": {
            "description": "Finished; look at each result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "integer"
                        },
                        "failed": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "index": {
                                "type": "integer"
                              },
                              "to": {
                                "type": "string"
                              },
                              "status": {
                                "type": "string",
                                "enum": [
                                  "sent",
                                  "failed"
                                ]
                              },
                              "type": {
                                "type": "string"
                              },
                              "message_id": {
                                "type": "string"
                              },
                              "whatsapp_id": {
                                "type": "string",
                                "format": "uuid"
                              },
                              "error": {
                                "type": "string",
                                "description": "For a failed row: MISSING_TO, MISSING_CONTENT, INVALID_ACCOUNT_ID, NO_CONNECTED_ACCOUNT, `PLAN_LIMIT (<limit>)` or `GATEWAY_<http status>`"
                              },
                              "detail": {
                                "type": "string",
                                "description": "For a gateway failure: the start of what the gateway answered"
                              },
                              "id": {
                                "type": "string",
                                "format": "uuid",
                                "description": "For a sent row: the id of this send, as in POST /whatsapp/send"
                              }
                            },
                            "required": [
                              "index",
                              "to",
                              "status"
                            ]
                          }
                        }
                      },
                      "required": [
                        "sent",
                        "failed",
                        "total",
                        "results"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` (no messages) or `TOO_MANY_MESSAGES` (more than 1,000).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/whatsapp/accounts": {
      "get": {
        "operationId": "get_whatsapp_accounts",
        "summary": "List connected WhatsApp numbers",
        "tags": [
          "WhatsApp"
        ],
        "description": "Only numbers that are connected right now are listed.\n\nScope: `accounts:read`.",
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:read",
        "responses": {
          "200": {
            "description": "The numbers, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "display_name": {
                            "type": "string",
                            "description": "Empty when none was set"
                          },
                          "phone": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "connected"
                            ]
                          },
                          "paired_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true
                          }
                        },
                        "required": [
                          "id",
                          "display_name",
                          "phone",
                          "status",
                          "paired_at"
                        ]
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/whatsapp/link": {
      "post": {
        "operationId": "post_whatsapp_link",
        "summary": "Start connecting a WhatsApp number",
        "tags": [
          "WhatsApp"
        ],
        "description": "Starts a pairing on the organization's gateway. Then fetch the QR code from `qr_url`, scan it in WhatsApp (Linked devices), and poll `status_url`.\n\nScope: `accounts:write`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "display_name": {
                    "type": "string"
                  }
                },
                "required": [
                  "phone"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:write",
        "responses": {
          "200": {
            "description": "Pairing started",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "phone": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "pending"
                          ]
                        },
                        "qr_url": {
                          "type": "string"
                        },
                        "status_url": {
                          "type": "string"
                        },
                        "instructions": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` or `VALIDATION` (no phone).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE`, `PLAN_LIMIT` (the plan's number limit) or `NOT_YOUR_NUMBER`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`GATEWAY_SETUP_REQUIRED`: the gateway app has never been started. This one answer has no `error` field.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        false
                      ]
                    },
                    "code": {
                      "type": "string",
                      "enum": [
                        "GATEWAY_SETUP_REQUIRED"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "install_url": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "`INTERNAL_ERROR`: the organization's gateway record could not be read.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/whatsapp/qr": {
      "get": {
        "operationId": "get_whatsapp_qr",
        "summary": "Get the QR code of a pairing",
        "tags": [
          "WhatsApp"
        ],
        "parameters": [
          {
            "name": "phone",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The number being connected"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:write",
        "description": "Scope: `accounts:write`.",
        "responses": {
          "200": {
            "description": "The QR code (`qr`) and the pairing event. The body is the gateway's own JSON, **not** the usual envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION`: no phone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_GATEWAY`: the organization has no gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/whatsapp/status": {
      "get": {
        "operationId": "get_whatsapp_status",
        "summary": "Get the connection status of a number",
        "tags": [
          "WhatsApp"
        ],
        "parameters": [
          {
            "name": "phone",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The number being connected"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:read",
        "description": "Scope: `accounts:read`.",
        "responses": {
          "200": {
            "description": "`status` (for example `connected` or `waiting_qr`) and `jid`. Trust `status`, not `connected`. The body is the gateway's own JSON, **not** the usual envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION`: no phone.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_GATEWAY`: the organization has no gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`WHATSAPP_NOT_CONNECTED` or `WHATSAPP_DISCONNECTED`: the number is not linked on the gateway.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`GATEWAY_CLOSED` (the gateway app is not running) or `GATEWAY_ERROR` (anything else the gateway reports).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages": {
      "get": {
        "operationId": "get_messages",
        "summary": "List received messages",
        "tags": [
          "Messages"
        ],
        "description": "Inbound messages of every channel (WhatsApp, SMS, email, web chat), newest first. Messages without a contact are left out.\n\nScope: `messages:read`.",
        "parameters": [
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only messages created after this time (RFC 3339). A value that is not a time answers 500."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 500
            },
            "description": "Above 500 is treated as 500."
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:read",
        "responses": {
          "200": {
            "description": "Messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "contact_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "content": {
                            "type": "string"
                          },
                          "sender_name": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "`INTERNAL_ERROR`, also for an unreadable `since`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/sms/send": {
      "post": {
        "operationId": "post_sms_send",
        "summary": "Queue an SMS",
        "tags": [
          "SMS"
        ],
        "description": "Queues an SMS for the organization's phone (the SMS gateway app) to send. The answer is 201 as soon as it is queued; `message.status` webhooks report sent, delivered or failed. The message appears in the organization's conversations.\n\nScope: `messages:send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "message": {
                    "type": "string"
                  },
                  "device_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Which phone to send from (id from GET /sms/accounts). Default: the first connected SMS channel."
                  }
                },
                "required": [
                  "to",
                  "message"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "201": {
            "description": "Queued",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Message id"
                        },
                        "conversation_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "to": {
                          "type": "string"
                        },
                        "content": {
                          "type": "string",
                          "description": "The text as queued, including a plan signature"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "pending"
                          ]
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` (no `to` or no `message`) or `INVALID_DEVICE_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "`NO_SMS_DEVICE`: no SMS phone is connected (or not the one asked for).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/sms/messages": {
      "get": {
        "operationId": "get_sms_messages",
        "summary": "List SMS messages",
        "tags": [
          "SMS"
        ],
        "description": "SMS in both directions, newest first.\n\nScope: `messages:read`.",
        "parameters": [
          {
            "name": "direction",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            }
          },
          {
            "name": "since",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "description": "Only messages created after this time (RFC 3339). A value that is not a time answers 500."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 100,
              "maximum": 500
            },
            "description": "Above 500 is treated as 500."
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:read",
        "responses": {
          "200": {
            "description": "Messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "conversation_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "contact_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "direction": {
                            "type": "string",
                            "enum": [
                              "inbound",
                              "outbound"
                            ]
                          },
                          "content": {
                            "type": "string"
                          },
                          "sender_name": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "pending",
                              "sent",
                              "delivered",
                              "read",
                              "failed"
                            ]
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "500": {
            "description": "`INTERNAL_ERROR`, also for an unreadable `since`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/sms/accounts": {
      "get": {
        "operationId": "get_sms_accounts",
        "summary": "List SMS phones",
        "tags": [
          "SMS"
        ],
        "description": "The phones running the SMS gateway app for this organization.\n\nScope: `accounts:read`.",
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:read",
        "responses": {
          "200": {
            "description": "Phones, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "model": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "description": "online, offline or error"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/email/send": {
      "post": {
        "operationId": "post_email_send",
        "summary": "Send an email",
        "tags": [
          "Email"
        ],
        "description": "Sends one email through the organization's own email channel and waits for the result. The message appears in the organization's conversations.\n\nScope: `messages:send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Recipient email address"
                  },
                  "subject": {
                    "type": "string",
                    "description": "Default: (no subject)"
                  },
                  "message": {
                    "type": "string",
                    "description": "Body, HTML or plain text"
                  },
                  "channel_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Which email channel to send from. Default: the organization's connected email channel."
                  }
                },
                "required": [
                  "to",
                  "message"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:send",
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Message id"
                        },
                        "conversation_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "channel_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "to": {
                          "type": "string"
                        },
                        "subject": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "sent"
                          ]
                        },
                        "via": {
                          "type": "string",
                          "description": "How it was handed over"
                        },
                        "provider_message_id": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`, `INVALID_EMAIL`, `INVALID_SUBJECT` or `INVALID_CHANNEL`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`CHANNEL_NOT_FOUND` or `NO_EMAIL_CHANNEL`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "The email service refused the message; the code says why.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "504": {
            "description": "`SEND_TIMEOUT`: the mail server did not answer in 30 seconds.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/otp/send": {
      "post": {
        "operationId": "post_otp_send",
        "summary": "Send a one-time code",
        "tags": [
          "OTP"
        ],
        "description": "Makes a numeric code, remembers it for the recipient and sends it by WhatsApp or SMS. Sending again replaces the earlier code.\n\nScope: `otp:send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "whatsapp",
                      "sms"
                    ],
                    "default": "whatsapp"
                  },
                  "length": {
                    "type": "integer",
                    "default": 6,
                    "description": "4 to 8; anything else means 6"
                  },
                  "expiry_seconds": {
                    "type": "integer",
                    "default": 300,
                    "description": "60 to 900; anything else means 300"
                  },
                  "template": {
                    "type": "string",
                    "description": "Your own text. It must contain {code}."
                  },
                  "account_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "WhatsApp number to send from"
                  },
                  "device_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "SMS phone to send from"
                  }
                },
                "required": [
                  "to"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "otp:send",
        "responses": {
          "200": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "sent": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "to": {
                          "type": "string"
                        },
                        "channel": {
                          "type": "string"
                        },
                        "expires_in": {
                          "type": "integer",
                          "description": "Seconds"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`, `INVALID_CHANNEL` or `INVALID_TEMPLATE`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "502": {
            "description": "`SEND_FAILED`: the code could not be sent; the message says why.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/otp/verify": {
      "post": {
        "operationId": "post_otp_verify",
        "summary": "Check a one-time code",
        "tags": [
          "OTP"
        ],
        "description": "Always answers 200; look at `verified`. A correct code can be used once. After 5 wrong tries the code is thrown away.\n\nScope: `otp:verify`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "to": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "code": {
                    "type": "string"
                  }
                },
                "required": [
                  "to",
                  "code"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "otp:verify",
        "responses": {
          "200": {
            "description": "Checked",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "verified": {
                          "type": "boolean"
                        },
                        "reason": {
                          "type": "string",
                          "enum": [
                            "expired_or_not_found",
                            "invalid_code",
                            "too_many_attempts"
                          ]
                        },
                        "attempts_left": {
                          "type": "integer"
                        }
                      },
                      "required": [
                        "verified"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`: no `to` or no `code`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/contacts": {
      "post": {
        "operationId": "post_contacts",
        "summary": "Create or update a contact",
        "tags": [
          "Contacts"
        ],
        "description": "Creates a contact. When a contact with the same phone already exists it is updated instead (name and email, when sent) and its id is answered. Tags are only stored on a new contact.\n\nScope: `contacts:write`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "phone": {
                    "type": "string",
                    "description": "Phone number with country code. A leading + is accepted and removed."
                  },
                  "email": {
                    "type": "string"
                  },
                  "tags": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                },
                "description": "phone or email is required"
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "contacts:write",
        "responses": {
          "201": {
            "description": "Created or updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "phone": {
                          "type": "string"
                        },
                        "email": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` or `VALIDATION` (neither phone nor email).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "`INTERNAL_ERROR`, for example an email-only contact whose email already exists.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/contacts/{id}": {
      "delete": {
        "operationId": "delete_contacts_id",
        "summary": "Delete a contact",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Contact id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "contacts:write",
        "description": "Scope: `contacts:write`.",
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "description": "false when there was nothing with that id in the organization"
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/groups": {
      "post": {
        "operationId": "post_groups",
        "summary": "Create a contact group",
        "tags": [
          "Contacts"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "description": {
                    "type": "string"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "contacts:write",
        "description": "Scope: `contacts:write`.",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION`: no name.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/groups/{id}": {
      "delete": {
        "operationId": "delete_groups_id",
        "summary": "Delete a contact group",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Group id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "contacts:write",
        "description": "Scope: `contacts:write`.",
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "description": "false when there was nothing with that id in the organization"
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/groups/{id}/contacts": {
      "post": {
        "operationId": "post_groups_id_contacts",
        "summary": "Add contacts to a group",
        "tags": [
          "Contacts"
        ],
        "description": "Ids that are not contacts of the organization are skipped.\n\nScope: `contacts:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Group id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "contact_ids": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  }
                },
                "required": [
                  "contact_ids"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "contacts:write",
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "added": {
                          "type": "integer",
                          "description": "How many were newly added"
                        },
                        "group_id": {
                          "type": "string",
                          "format": "uuid"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID` or `VALIDATION` (no contact_ids).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`: no such group.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/quick-replies": {
      "post": {
        "operationId": "post_quick_replies",
        "summary": "Create a quick reply",
        "tags": [
          "Quick replies"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "title": {
                    "type": "string"
                  },
                  "content": {
                    "type": "string"
                  },
                  "shortcut": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "default": "whatsapp"
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "quick-replies:write",
        "description": "Scope: `quick-replies:write`.",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "title": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION`: no content.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/quick-replies/{id}": {
      "delete": {
        "operationId": "delete_quick_replies_id",
        "summary": "Delete a quick reply",
        "tags": [
          "Quick replies"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Quick reply id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "quick-replies:write",
        "description": "Scope: `quick-replies:write`.",
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "description": "false when there was nothing with that id in the organization"
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/templates": {
      "get": {
        "operationId": "get_templates",
        "summary": "List message templates",
        "tags": [
          "Templates"
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "templates:read",
        "description": "Scope: `templates:read`.",
        "responses": {
          "200": {
            "description": "Templates, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "name": {
                            "type": "string"
                          },
                          "channel": {
                            "type": "string"
                          },
                          "content": {
                            "type": "string"
                          },
                          "variables": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "has_spintax": {
                            "type": "boolean"
                          },
                          "media_url": {
                            "type": "string",
                            "description": "Empty when none"
                          },
                          "media_type": {
                            "type": "string",
                            "description": "Empty when none"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "post_templates",
        "summary": "Create a message template",
        "tags": [
          "Templates"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "default": "whatsapp"
                  },
                  "content": {
                    "type": "string"
                  },
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "has_spintax": {
                    "type": "boolean"
                  },
                  "media_url": {
                    "type": "string"
                  },
                  "media_type": {
                    "type": "string"
                  }
                },
                "required": [
                  "name",
                  "content"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "templates:write",
        "description": "Scope: `templates:write`.",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION`: no name or no content.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/templates/{id}": {
      "put": {
        "operationId": "put_templates_id",
        "summary": "Update a message template",
        "tags": [
          "Templates"
        ],
        "description": "An empty or absent `name`, `channel` or `content` is left as it is. `variables`, `has_spintax`, `media_url` and `media_type` are **always** replaced: leave them out and they are cleared.\n\nScope: `templates:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Template id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "default": "whatsapp"
                  },
                  "content": {
                    "type": "string"
                  },
                  "variables": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "has_spintax": {
                    "type": "boolean"
                  },
                  "media_url": {
                    "type": "string"
                  },
                  "media_type": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "templates:write",
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "updated": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID` or `INVALID_BODY`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "operationId": "delete_templates_id",
        "summary": "Delete a message template",
        "tags": [
          "Templates"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Template id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "templates:write",
        "description": "Scope: `templates:write`.",
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "description": "false when there was nothing with that id in the organization"
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/lead-forms": {
      "get": {
        "operationId": "get_lead_forms",
        "summary": "List lead forms",
        "tags": [
          "Lead forms"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            },
            "description": "A value above the maximum falls back to 20."
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "lead-forms:read",
        "description": "Scope: `lead-forms:read`.",
        "responses": {
          "200": {
            "description": "Lead forms",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/LeadForm"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "total",
                    "page",
                    "per_page"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "operationId": "post_lead_forms",
        "summary": "Create a lead form",
        "tags": [
          "Lead forms"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "fields": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/LeadFormField"
                    },
                    "minItems": 1
                  },
                  "submit_action": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "What happens on a submission. Default: {\"create_contact\": true}."
                  }
                },
                "required": [
                  "name",
                  "fields"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "lead-forms:write",
        "description": "Scope: `lead-forms:write`.",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "embed_code": {
                          "type": "string",
                          "description": "HTML to paste into a page"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`VALIDATION`: no name or no fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/lead-forms/{id}/embed": {
      "get": {
        "operationId": "get_lead_forms_id_embed",
        "summary": "Get the embed code of a lead form",
        "tags": [
          "Lead forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Lead form id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "lead-forms:read",
        "description": "Scope: `lead-forms:read`.",
        "responses": {
          "200": {
            "description": "Embed code",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "embed_code": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/lead-forms/{id}/submissions": {
      "get": {
        "operationId": "get_lead_forms_id_submissions",
        "summary": "List the submissions of a lead form",
        "tags": [
          "Lead forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Lead form id"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            },
            "description": "A value above the maximum falls back to 20."
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "lead-forms:read",
        "description": "Scope: `lead-forms:read`.",
        "responses": {
          "200": {
            "description": "Submissions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "form_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "contact_id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "data": {
                            "type": "object",
                            "additionalProperties": true,
                            "description": "What the visitor typed, keyed by field name"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "total",
                    "page",
                    "per_page"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/lead-forms/{id}": {
      "delete": {
        "operationId": "delete_lead_forms_id",
        "summary": "Delete a lead form",
        "tags": [
          "Lead forms"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Lead form id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "lead-forms:write",
        "description": "Scope: `lead-forms:write`.",
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "deleted": {
                          "type": "boolean",
                          "description": "false when there was nothing with that id in the organization"
                        }
                      },
                      "required": [
                        "deleted"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/campaigns": {
      "post": {
        "operationId": "post_campaigns",
        "summary": "Create a campaign",
        "tags": [
          "Campaigns"
        ],
        "description": "Creates a campaign as a draft, schedules it (`schedule_at`), or starts sending at once (`send_now`). `schedule_at` wins when both are sent.\n\nScope: `campaigns:write`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "message_content": {
                    "type": "string"
                  },
                  "channel": {
                    "type": "string",
                    "enum": [
                      "whatsapp",
                      "sms",
                      "multi"
                    ],
                    "default": "whatsapp",
                    "description": "Any other value means whatsapp"
                  },
                  "audience_type": {
                    "type": "string",
                    "default": "manual"
                  },
                  "audience_filter": {
                    "type": "object",
                    "additionalProperties": true
                  },
                  "whatsapp_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Required for whatsapp and multi"
                  },
                  "sms_device_id": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Required for sms and multi"
                  },
                  "send_now": {
                    "type": "boolean"
                  },
                  "schedule_at": {
                    "type": "string",
                    "format": "date-time"
                  }
                },
                "required": [
                  "name",
                  "message_content"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "campaigns:write",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "name": {
                          "type": "string"
                        },
                        "channel": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string",
                          "enum": [
                            "draft",
                            "scheduled",
                            "sending"
                          ]
                        },
                        "scheduled_at": {
                          "type": "string",
                          "description": "As sent; empty when not scheduled"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`, `WHATSAPP_ID_REQUIRED`, `INVALID_WHATSAPP_ID`, `WHATSAPP_NOT_FOUND`, `SMS_DEVICE_ID_REQUIRED`, `INVALID_SMS_DEVICE_ID` or `SMS_DEVICE_NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/chat-widgets": {
      "get": {
        "operationId": "get_chat_widgets",
        "summary": "List chat widgets",
        "tags": [
          "Web chat"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1,
              "maximum": 100
            },
            "description": "A value above the maximum falls back to 20."
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "chat-widgets:read",
        "description": "Scope: `chat-widgets:read`.",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "200": {
            "description": "Widgets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ChatWidget"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "total",
                    "page",
                    "per_page"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "post": {
        "operationId": "post_chat_widgets",
        "summary": "Create a chat widget",
        "tags": [
          "Web chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "config": {
                    "$ref": "#/components/schemas/ChatWidgetConfig"
                  },
                  "active": {
                    "type": "boolean",
                    "description": "Default true"
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "chat-widgets:write",
        "description": "Scope: `chat-widgets:write`.",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/ChatWidget"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`, or `VALIDATION_ERROR` with `errors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "`INSUFFICIENT_SCOPE` (the key lacks the scope) or `PLAN_LIMIT` (the plan's limit is used up).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/chat-widgets/{id}": {
      "get": {
        "operationId": "get_chat_widgets_id",
        "summary": "Get a chat widget",
        "tags": [
          "Web chat"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Chat widget id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "chat-widgets:read",
        "description": "Scope: `chat-widgets:read`.",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "200": {
            "description": "Widget",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/ChatWidget"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "404": {
            "description": "`NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "put": {
        "operationId": "put_chat_widgets_id",
        "summary": "Update a chat widget",
        "tags": [
          "Web chat"
        ],
        "description": "Send only what changes.\n\nScope: `chat-widgets:write`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Chat widget id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string"
                  },
                  "config": {
                    "$ref": "#/components/schemas/ChatWidgetConfig"
                  },
                  "active": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "chat-widgets:write",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "200": {
            "description": "Updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/ChatWidget"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY`, or `VALIDATION_ERROR` with `errors`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      }
    },
    "/conversations": {
      "get": {
        "operationId": "get_conversations",
        "summary": "List web chat conversations",
        "tags": [
          "Web chat"
        ],
        "description": "Only conversations of the **web chat** channel are listed here. WhatsApp, SMS and email conversations are not available through the public API; use GET /messages for received messages of every channel.\n\nScope: `conversations:read`.",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 30,
              "minimum": 1,
              "maximum": 200
            },
            "description": "A value above the maximum falls back to 20."
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "For example open or closed"
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "conversations:read",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "200": {
            "description": "Conversations",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Conversation"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "total",
                    "page",
                    "per_page"
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      }
    },
    "/conversations/{id}/messages": {
      "get": {
        "operationId": "get_conversations_id_messages",
        "summary": "List the messages of a conversation",
        "tags": [
          "Web chat"
        ],
        "description": "Works for a conversation of any channel when its id is known.\n\nScope: `conversations:read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Conversation id"
          },
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1,
              "minimum": 1
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 50,
              "minimum": 1,
              "maximum": 200
            },
            "description": "A value above the maximum falls back to 20."
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "conversations:read",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "200": {
            "description": "Messages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Message"
                      }
                    },
                    "total": {
                      "type": "integer"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "per_page": {
                      "type": "integer"
                    }
                  },
                  "required": [
                    "success",
                    "data",
                    "total",
                    "page",
                    "per_page"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "404": {
            "description": "`NO_CONVERSATION`: no such conversation in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      },
      "post": {
        "operationId": "post_conversations_id_messages",
        "summary": "Reply in a web chat conversation",
        "tags": [
          "Web chat"
        ],
        "description": "Sends a reply to the website visitor. Text longer than 4,000 characters is cut. Only web chat conversations can be answered this way.\n\nScope: `conversations:reply`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Conversation id"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "content": {
                    "type": "string"
                  }
                },
                "required": [
                  "content"
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "conversations:reply",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "201": {
            "description": "Sent",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "Message id"
                        },
                        "conversation_id": {
                          "type": "string",
                          "format": "uuid"
                        },
                        "content": {
                          "type": "string"
                        },
                        "direction": {
                          "type": "string",
                          "enum": [
                            "outbound"
                          ]
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_BODY` (no content), or `VALIDATION_ERROR` for a bad id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "`NOT_LIVECHAT`: the conversation is not a web chat.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NO_CONVERSATION`: no such conversation in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      }
    },
    "/conversations/{id}/read": {
      "post": {
        "operationId": "post_conversations_id_read",
        "summary": "Mark a conversation as read",
        "tags": [
          "Web chat"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "Conversation id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "conversations:reply",
        "description": "Scope: `conversations:reply`.",
        "x-rate-limit": {
          "limit": 300,
          "window_seconds": 60,
          "per": "organization",
          "shared_by": "all /chat-widgets and /conversations routes"
        },
        "responses": {
          "200": {
            "description": "Done",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "404": {
            "description": "`NO_CONVERSATION`: no such conversation in this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Either `RATE_LIMITED` (the API key is over its own limit; JSON envelope, with `Retry-After`), or more than 300 requests in a minute on the web chat routes of this organization (plain text, not the envelope).",
            "headers": {
              "Retry-After": {
                "schema": {
                  "type": "integer"
                },
                "description": "Seconds to wait (key limit only)"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              },
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          }
        }
      }
    },
    "/gateway/register": {
      "post": {
        "operationId": "post_gateway_register",
        "summary": "Gateway app: register",
        "tags": [
          "Gateway app"
        ],
        "description": "Used by the WaSMS gateway app to say it is running. Not meant for customer integrations.\n\nScope: `accounts:read`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "device_name": {
                    "type": "string",
                    "description": "Default: Local Gateway"
                  },
                  "os": {
                    "type": "string"
                  },
                  "arch": {
                    "type": "string"
                  },
                  "local_url": {
                    "type": "string"
                  },
                  "tunnel_url": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "description": "Default: online"
                  },
                  "message": {
                    "type": "string"
                  },
                  "version": {
                    "type": "string"
                  },
                  "timestamp": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:read",
        "x-internal": true,
        "responses": {
          "200": {
            "description": "Recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "tenant_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "The organization's id"
                        },
                        "device_name": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "tunnel_url": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/gateway/heartbeat": {
      "post": {
        "operationId": "post_gateway_heartbeat",
        "summary": "Gateway app: heartbeat",
        "tags": [
          "Gateway app"
        ],
        "description": "Used by the WaSMS gateway app to say it is running. Not meant for customer integrations. The body is optional.\n\nScope: `accounts:read`.",
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "accounts:read",
        "x-internal": true,
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "device_name": {
                    "type": "string",
                    "description": "Default: Local Gateway"
                  },
                  "os": {
                    "type": "string"
                  },
                  "arch": {
                    "type": "string"
                  },
                  "local_url": {
                    "type": "string"
                  },
                  "tunnel_url": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "description": "Default: online"
                  },
                  "message": {
                    "type": "string"
                  },
                  "version": {
                    "type": "string"
                  },
                  "timestamp": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "tenant_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "The organization's id"
                        },
                        "device_name": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "tunnel_url": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/gateway/local/report": {
      "post": {
        "operationId": "post_gateway_local_report",
        "summary": "Gateway app: status report",
        "tags": [
          "Gateway app"
        ],
        "description": "Used by the WaSMS gateway app to say it is running. Not meant for customer integrations.\n\nAny valid API key; no scope needed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "device_name": {
                    "type": "string",
                    "description": "Default: Local Gateway"
                  },
                  "os": {
                    "type": "string"
                  },
                  "arch": {
                    "type": "string"
                  },
                  "local_url": {
                    "type": "string"
                  },
                  "tunnel_url": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "description": "Default: online"
                  },
                  "message": {
                    "type": "string"
                  },
                  "version": {
                    "type": "string"
                  },
                  "timestamp": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "",
        "x-internal": true,
        "responses": {
          "200": {
            "description": "Recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "ok": {
                          "type": "boolean",
                          "enum": [
                            true
                          ]
                        },
                        "tenant_id": {
                          "type": "string",
                          "format": "uuid",
                          "description": "The organization's id"
                        },
                        "device_name": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "tunnel_url": {
                          "type": "string"
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/ValidationError"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/learn/categories": {
      "get": {
        "operationId": "get_learn_categories",
        "summary": "Learn: categories",
        "tags": [
          "Learn"
        ],
        "description": "Public help content of the WaSMS website. No API key.",
        "security": [],
        "responses": {
          "200": {
            "description": "Categories",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "icon": {
                            "type": "string"
                          },
                          "sort_order": {
                            "type": "integer"
                          },
                          "seo_title": {
                            "type": "string"
                          },
                          "seo_desc": {
                            "type": "string"
                          },
                          "hero_image_url": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/learn/industries": {
      "get": {
        "operationId": "get_learn_industries",
        "summary": "Learn: industries",
        "tags": [
          "Learn"
        ],
        "description": "Public help content of the WaSMS website. No API key.",
        "security": [],
        "responses": {
          "200": {
            "description": "Industries",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid"
                          },
                          "slug": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "icon": {
                            "type": "string"
                          },
                          "sort_order": {
                            "type": "integer"
                          },
                          "seo_title": {
                            "type": "string"
                          },
                          "seo_desc": {
                            "type": "string"
                          },
                          "hero_image_url": {
                            "type": "string"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/learn/articles": {
      "get": {
        "operationId": "get_learn_articles",
        "summary": "Learn: articles",
        "tags": [
          "Learn"
        ],
        "description": "Public help content of the WaSMS website. No API key.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "industry",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "intent",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "next_cursor of the previous page"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Articles",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "articles": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/LearnArticleSummary"
                          }
                        },
                        "next_cursor": {
                          "type": "string",
                          "nullable": true
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/learn/search": {
      "get": {
        "operationId": "get_learn_search",
        "summary": "Learn: search",
        "tags": [
          "Learn"
        ],
        "description": "Public help content of the WaSMS website. No API key.",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 20
            }
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Results, each with a `rank`",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "properties": {
                        "query": {
                          "type": "string"
                        },
                        "results": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/LearnArticleSummary"
                          }
                        }
                      }
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_QUERY`: no q.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/learn/sitemap.xml": {
      "get": {
        "operationId": "get_learn_sitemap_xml",
        "summary": "Learn: sitemap",
        "tags": [
          "Learn"
        ],
        "description": "Public help content of the WaSMS website. No API key.",
        "security": [],
        "responses": {
          "200": {
            "description": "XML sitemap",
            "content": {
              "application/xml": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/learn/articles/{cat}/{slug}": {
      "get": {
        "operationId": "get_learn_articles_cat_slug",
        "summary": "Learn: one article",
        "tags": [
          "Learn"
        ],
        "description": "Public help content of the WaSMS website. No API key.",
        "parameters": [
          {
            "name": "cat",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Category slug"
          },
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Article slug"
          }
        ],
        "security": [],
        "responses": {
          "200": {
            "description": "Article",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "The article: the summary fields plus body_md, body_html_cached, the SEO fields, faq_items and external_links"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "success",
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/openapi.json": {
      "get": {
        "operationId": "get_openapi_json",
        "summary": "This document",
        "tags": [
          "Meta"
        ],
        "description": "The OpenAPI description of the public API. No API key.",
        "security": [],
        "responses": {
          "200": {
            "description": "OpenAPI 3.0 document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          }
        }
      }
    },
    "/mcp": {
      "post": {
        "operationId": "post_mcp",
        "summary": "MCP server",
        "tags": [
          "Meta"
        ],
        "description": "A Model Context Protocol endpoint (streamable HTTP, JSON answers) for AI clients. JSON-RPC 2.0 in the body: `initialize`, `ping`, `tools/list`, `tools/call`. Which tools exist depends on the scopes of the key; every tool call runs the matching route of this API with the same key.\n\nAny valid API key; no scope needed.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "jsonrpc": {
                        "type": "string",
                        "enum": [
                          "2.0"
                        ]
                      },
                      "id": {
                        "description": "String or number. Absent for a notification."
                      },
                      "method": {
                        "type": "string"
                      },
                      "params": {
                        "type": "object",
                        "additionalProperties": true
                      }
                    },
                    "required": [
                      "jsonrpc",
                      "method"
                    ]
                  },
                  {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "jsonrpc": {
                          "type": "string",
                          "enum": [
                            "2.0"
                          ]
                        },
                        "id": {
                          "description": "String or number. Absent for a notification."
                        },
                        "method": {
                          "type": "string"
                        },
                        "params": {
                          "type": "object",
                          "additionalProperties": true
                        }
                      },
                      "required": [
                        "jsonrpc",
                        "method"
                      ]
                    }
                  }
                ]
              }
            }
          }
        },
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "",
        "responses": {
          "200": {
            "description": "JSON-RPC response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true,
                  "description": "A JSON-RPC 2.0 response (or an array of them for a batch)"
                }
              }
            }
          },
          "202": {
            "description": "A notification was accepted; no body."
          },
          "400": {
            "description": "The body is not JSON: a JSON-RPC error with code -32700.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "additionalProperties": true
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/messages/{id}": {
      "get": {
        "operationId": "get_messages_id",
        "summary": "Get the status of one message",
        "tags": [
          "Messages"
        ],
        "description": "Whether a message was delivered and read. `id` is the id a send answered (POST /whatsapp/send, /whatsapp/bulk, /whatsapp/poll, /sms/send, /email/send) or the id of any message of the organization.\n\nFor WhatsApp: `delivered` means the message reached the recipient's phone. `read` is reported only when the recipient has read receipts switched on in their WhatsApp (and the organization's own number has them on too); otherwise the message stays `delivered`. Messages sent to a group stay `sent`. Only messages sent through WaSMS are known. The status of a WhatsApp message sent through this API is kept for 30 days.\n\nDo not poll this for every message; subscribe to the `message.status` webhook.\n\nScope: `messages:read`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "The id a send answered, or a message id"
          }
        ],
        "security": [
          {
            "ApiKey": []
          },
          {
            "ApiKeyQuery": []
          }
        ],
        "x-scope": "messages:read",
        "responses": {
          "200": {
            "description": "The status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "success",
                    "data"
                  ],
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "data": {
                      "$ref": "#/components/schemas/MessageStatus"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "`INVALID_ID`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "`NOT_FOUND`: no such message in this organization (or a WhatsApp send older than 30 days).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/InsufficientScope"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "description": "Authorization: Bearer wasms_..."
      },
      "ApiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "secret",
        "description": "For systems that cannot send a header"
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "`UNAUTHORIZED`: the key is missing, malformed, unknown or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "InsufficientScope": {
        "description": "`INSUFFICIENT_SCOPE`: the key does not have the scope this route needs.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ValidationError": {
        "description": "`VALIDATION_ERROR`: a path or body value is not valid.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ValidationError"
            }
          }
        }
      },
      "RateLimited": {
        "description": "`RATE_LIMITED`: the API key made more requests this minute than its limit allows. `Retry-After` says how many seconds until the next minute starts.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string",
            "description": "The code, for example INVALID_BODY"
          },
          "code": {
            "type": "string",
            "description": "The same code"
          },
          "message": {
            "type": "string",
            "description": "What went wrong, in words"
          }
        },
        "required": [
          "success",
          "error"
        ]
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "string",
            "enum": [
              "VALIDATION_ERROR"
            ]
          },
          "code": {
            "type": "string",
            "enum": [
              "VALIDATION_ERROR"
            ]
          },
          "errors": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "One sentence per field"
          }
        },
        "required": [
          "success",
          "error",
          "code"
        ]
      },
      "LeadFormField": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "text, email, phone, textarea or select"
          },
          "label": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "options": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "For select"
          }
        },
        "required": [
          "name",
          "type"
        ]
      },
      "LeadForm": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization's id"
          },
          "name": {
            "type": "string"
          },
          "fields": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LeadFormField"
            }
          },
          "submit_action": {
            "type": "object",
            "additionalProperties": true
          },
          "embed_code": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "submission_count": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ChatWidgetConfig": {
        "type": "object",
        "additionalProperties": true,
        "description": "Appearance and behaviour of the widget. All optional.",
        "properties": {
          "color": {
            "type": "string"
          },
          "position": {
            "type": "string",
            "description": "bottom-right or bottom-left"
          },
          "greeting": {
            "type": "string"
          },
          "avatar_url": {
            "type": "string"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "whatsapp, sms, web"
          },
          "title": {
            "type": "string"
          },
          "subtitle": {
            "type": "string"
          },
          "button_label": {
            "type": "string"
          },
          "whatsapp_message": {
            "type": "string"
          },
          "sms_number": {
            "type": "string"
          },
          "sms_message": {
            "type": "string"
          },
          "allowed_origins": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "ChatWidget": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization's id"
          },
          "name": {
            "type": "string"
          },
          "config": {
            "$ref": "#/components/schemas/ChatWidgetConfig"
          },
          "embed_code": {
            "type": "string"
          },
          "active": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "Conversation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization's id"
          },
          "contact_id": {
            "type": "string",
            "format": "uuid"
          },
          "contact_name": {
            "type": "string"
          },
          "contact_phone": {
            "type": "string"
          },
          "contact_avatar": {
            "type": "string"
          },
          "account_phone": {
            "type": "string"
          },
          "channel_id": {
            "type": "string",
            "format": "uuid"
          },
          "channel_type": {
            "type": "string"
          },
          "channel_name": {
            "type": "string"
          },
          "assigned_to": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "assigned_user_name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "unread_count": {
            "type": "integer"
          },
          "last_message_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_message_preview": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "pinned_at": {
            "type": "string",
            "format": "date-time"
          },
          "is_group": {
            "type": "boolean"
          }
        }
      },
      "Message": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "description": "The organization's id"
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "channel_type": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "media_url": {
            "type": "string"
          },
          "media_type": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "sender_name": {
            "type": "string"
          },
          "sent_by_name": {
            "type": "string"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        }
      },
      "LearnArticleSummary": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "slug": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "subtitle": {
            "type": "string"
          },
          "excerpt": {
            "type": "string"
          },
          "hero_image_url": {
            "type": "string"
          },
          "hero_image_alt": {
            "type": "string"
          },
          "read_minutes": {
            "type": "integer"
          },
          "word_count": {
            "type": "integer"
          },
          "primary_keyword": {
            "type": "string"
          },
          "intent": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "is_featured": {
            "type": "boolean"
          },
          "view_count": {
            "type": "integer"
          },
          "published_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "category": {
            "type": "object",
            "properties": {
              "slug": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "author": {
            "type": "object",
            "nullable": true,
            "properties": {
              "slug": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "avatar_url": {
                "type": "string"
              }
            }
          },
          "industries": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "MessageStatus": {
        "type": "object",
        "required": [
          "id",
          "channel",
          "status",
          "sent_at"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "channel": {
            "type": "string",
            "enum": [
              "whatsapp",
              "sms",
              "email",
              "web"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "sent",
              "delivered",
              "read",
              "failed"
            ]
          },
          "to": {
            "type": "string",
            "nullable": true,
            "description": "The recipient of a message the organization sent; null for a received message"
          },
          "provider_message_id": {
            "type": "string",
            "nullable": true,
            "description": "The id on the channel (the WhatsApp message id)"
          },
          "conversation_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true,
            "description": "null for a WhatsApp message sent through this API (it is not in a conversation)"
          },
          "sent_at": {
            "type": "string",
            "format": "date-time"
          },
          "delivered_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "WhatsApp only; null until reported"
          },
          "read_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "WhatsApp only; null until reported, and for ever when the recipient has read receipts switched off"
          }
        }
      }
    }
  }
}