openapi: 3.1.0
info:
  title: DMWire API
  version: 1.0.0
  description: |-
    DMWire lets an AI assistant or your own script send and receive WhatsApp and Telegram messages from your own accounts.

    Authenticate with an API key that starts with `dmw_live_`, sent as a Bearer token.

    Connect an account (`connect_whatsapp` or `connect_telegram`), send with `send_message`, and use `wait_for_messages` to receive inbound messages, or subscribe a webhook.

    Free tier limits: 50 sends per day and 10 new contacts per day. `get_usage` shows where you stand.
servers:
  - url: https://api.dmwire.ai/v1
tags:
  - name: Accounts
    description: Connect, inspect and disconnect the WhatsApp and Telegram accounts you send from.
  - name: Messages
    description: Send messages, read them back, and wait for replies.
  - name: Webhooks
    description: Get message and account events pushed to your own URL.
  - name: Usage
    description: Your sends and limits for the current period.
security:
  - ApiKeyAuth: []
components:
  schemas:
    WireError:
      type: object
      properties:
        error_code:
          type: string
        error:
          type: string
        retry_after_s:
          type: integer
    WireAccount:
      type: object
      properties:
        id:
          type: string
        channel:
          type: string
          enum:
            - whatsapp_web
            - telegram
        identifier:
          type: string
          description: The phone number, or the Telegram @username when no number is known.
        status:
          type: string
          enum:
            - connected
            - connecting
            - disconnected
            - restricted
        connected_at:
          type: string
          format: date-time
          nullable: true
        limits:
          type: object
          properties:
            sends_today:
              type: integer
            sends_cap:
              type: integer
            new_contacts_today:
              type: integer
            new_contacts_cap:
              type: integer
            ramp_day:
              type: integer
              nullable: true
    WireMessage:
      type: object
      properties:
        id:
          type: string
        account_id:
          type: string
          nullable: true
        direction:
          type: string
          enum:
            - inbound
            - outbound
        text:
          type: string
        media:
          type: object
          nullable: true
          properties:
            url:
              type: string
            content_type:
              type: string
              nullable: true
        status:
          type: string
        error:
          type: object
          nullable: true
          properties:
            code:
              type: integer
              nullable: true
            message:
              type: string
              nullable: true
        timestamp:
          type: string
          format: date-time
        contact:
          type: object
          properties:
            id:
              type: string
            phone:
              type: string
              nullable: true
            name:
              type: string
              nullable: true
    WebhookSubscription:
      type: object
      description: A webhook subscription configured on the account.
      properties:
        id:
          type: string
          description: Identifier for this subscription. Use it (or the exact name) as the webhookId path parameter in other webhook endpoints. Note that ids are positional and can shift after a deletion, so prefer addressing subscriptions by name.
          examples:
            - '0'
        name:
          type:
            - string
            - 'null'
          description: Display name for the subscription. Can also be used as the webhookId path parameter.
          examples:
            - Order updates hook
        url:
          type: string
          description: HTTPS URL that receives event payloads via POST.
          examples:
            - https://hooks.example.com/incoming
        subscribed_to:
          type: array
          description: Event types this subscription receives. See GET /webhooks/events for the full list of valid values.
          items:
            type: string
            enum:
              - message.received
              - message.sent
              - message.delivered
              - message.read
              - message.failed
              - account.connected
              - account.disconnected
              - account.restricted
              - account.limit_reached
          examples:
            - - message.received
              - message.sent
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the subscription was created.
          examples:
            - '2026-06-09T12:00:00.000Z'
        enabled:
          type: boolean
          description: The account's on/off switch for this subscription. Delivery only happens when the subscription is switched on. A subscription with no stored value (created before this field existed) reports true. Set via enabled on POST /webhooks or PUT /webhooks/{webhookId}.
          examples:
            - true
        retries_enabled:
          type: boolean
          description: Whether failed deliveries to this subscription are retried (at 1m, 5m, 30m and 2h). Off by default. Set via retries_enabled on POST /webhooks or PUT /webhooks/{webhookId}.
          examples:
            - false
        signing_enabled:
          type: boolean
          description: Whether deliveries to this subscription are signed with an HMAC-SHA256 signature. On when a signing secret is set. The secret itself is never returned here, read it from GET /webhooks/{webhookId}/signing-secret.
          examples:
            - false
        signing_secret_created_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the current signing secret was generated, or null when signing is off.
          examples:
            - '2026-07-15T09:30:00.000Z'
    WebhookHealthStatus:
      type: object
      description: Delivery-health information for a webhook URL. Null until the first delivery attempt has been made.
      properties:
        consecutive_failures:
          type: integer
          description: Number of delivery failures in a row. Resets to 0 on a successful delivery.
          examples:
            - 0
        total_failures:
          type: integer
          description: Total failed deliveries recorded for this URL.
          examples:
            - 7
        total_successes:
          type: integer
          description: Total successful deliveries recorded for this URL.
          examples:
            - 42
        is_disabled:
          type: boolean
          description: True when delivery to this URL has been paused automatically after repeated failures. Use the reenable endpoint to resume delivery.
          examples:
            - false
        disabled_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When delivery was paused, if it is currently paused.
        disabled_reason:
          type:
            - string
            - 'null'
          description: Human-readable explanation of why delivery was paused.
        last_failure:
          type:
            - object
            - 'null'
          description: Details of the most recent failed delivery, when one has occurred.
          properties:
            timestamp:
              type:
                - string
                - 'null'
              format: date-time
              description: When the failure happened.
            status_code:
              type:
                - integer
                - 'null'
              description: HTTP status code returned by the receiver, when available.
              examples:
                - 410
            failure_type:
              type: string
              description: Classification of the failure.
              enum:
                - permanent
                - temporary
                - timeout
                - network
                - unknown
            error_message:
              type: string
              description: Error message from the failed delivery attempt.
        last_success_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the most recent successful delivery happened.
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When health tracking started for this URL.
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When the health record was last updated.
    TelegramConnectRequest:
      type: object
      required:
        - phone_number
      properties:
        phone_number:
          type: string
          description: The account phone number to connect, in E.164 format.
          example: '+14155550100'
        mode:
          type: string
          enum:
            - code
            - qr
          default: code
          description: Login method. 'code' sends a one-time login code to the account; 'qr' returns a login token and QR URL to display for scanning.
        force_new:
          type: boolean
          description: When true, discards any existing session and starts fresh.
    TelegramConnectResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+14155550100'
        status:
          type: string
          description: Session status after initiation. 'code_required' (code mode) means a one-time login code was sent to the account; 'qr_required' (qr mode) means a login token and QR URL were issued for scanning; 'initializing' means the session is still starting up.
          enum:
            - code_required
            - qr_required
            - initializing
          example: code_required
        session_id:
          type:
            - string
            - 'null'
          description: Identifier of the started session, when available.
        login_token:
          type: string
          description: QR login token (qr mode only).
        qr_url:
          type: string
          description: Encoded QR login URL to display (qr mode only).
        connect_url:
          type:
            - string
            - 'null'
          description: A hosted page that finishes the connection on its own, hand this link to the account holder instead of building your own UI and polling. In code mode they enter the login code (and a two-step verification password if the account has one); in qr mode it shows a refreshing QR to scan from the Telegram app. Null if the link could not be generated; the verify-code / verify-password / status endpoints (and qr_url in qr mode) remain available as a fallback. The link works for about 30 minutes (connect_url_expires_at).
          example: https://api.dmwire.ai/v1/channels/telegram/connect/page?token=eyJhbGciOi...
        connect_url_expires_at:
          type:
            - integer
            - 'null'
          description: Unix epoch (ms) when connect_url stops working. Start a new connection to get a fresh link.
    TelegramVerifyCodeRequest:
      type: object
      required:
        - code
      properties:
        code:
          type: string
          description: The one-time login code received by the account.
          example: '12345'
    TelegramVerifyPasswordRequest:
      type: object
      required:
        - password
      properties:
        password:
          type: string
          description: The account's two-factor password.
    TelegramVerifyResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+14155550100'
        status:
          type: string
          description: Verification result. 'connected' means the channel is live; 'password_required' means a two-factor password must be submitted next.
          enum:
            - connected
            - password_required
          example: connected
        telegram_user_id:
          type:
            - string
            - 'null'
          description: The connected account identifier, when available.
        username:
          type:
            - string
            - 'null'
          description: The connected account username, when set.
    TelegramStatusResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+14155550100'
        status:
          type: string
          description: Current connection status.
          enum:
            - connected
            - code_required
            - password_required
            - initializing
            - disconnected
            - not_initialized
            - error
          example: connected
        telegram_user_id:
          type:
            - string
            - 'null'
          description: The connected account identifier, when available.
        live:
          type: boolean
          description: True when the status was read live from the connection service.
          example: true
    TelegramDisconnectResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+14155550100'
        status:
          type: string
          enum:
            - removed
          example: removed
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
          description: Human-readable error message.
        error_code:
          type: integer
          description: HTTP status code, present on authentication, authorization, not-found, and rate-limit errors.
    WhatsAppWebConnectRequest:
      type: object
      required:
        - phone_number
      properties:
        phone_number:
          type: string
          description: The WhatsApp number to connect, in E.164 format (for example +15551230000).
          example: '+15551230000'
        link_method:
          type: string
          enum:
            - qr
            - pairing_code
          default: qr
          description: How the phone is linked. 'qr' (default) shows a QR code to scan; 'pairing_code' returns an 8-character code to type on the phone under Linked devices, Link with phone number instead.
        force_new:
          type: boolean
          description: Discard any existing session for this number and start a fresh pairing.
          default: false
        import_contacts:
          type: boolean
          description: Import the device's existing contacts on first connection.
          default: false
        pause_ai_for_imported_contacts:
          type: boolean
          description: When importing contacts, keep automated replies paused for them.
          default: true
        import_existing_chats:
          type: boolean
          description: Import existing chat history on first connection. Requires import_contacts to be true.
          default: false
        mark_imported_contacts_as_private:
          type: boolean
          description: When importing contacts, create them as private (no messages stored or sent for them). Incompatible with import_existing_chats.
          default: false
    WhatsAppWebConnectResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+15551230000'
        session_id:
          type: string
          description: Identifier for the pairing session, used for support and correlation.
        status:
          type: string
          description: The pairing step. Begins at qr_pending while a QR code is being prepared.
          enum:
            - qr_pending
          example: qr_pending
        connect_url:
          type:
            - string
            - 'null'
          description: A hosted web page that displays the pairing QR code and refreshes itself automatically until the number is connected. Give this link to the end user to open in a browser and scan with WhatsApp, it handles QR rotation and shows a success state on its own, so no polling is required. Null only if the link could not be generated (use the poll_qr_path/poll_status_path fallback in that case).
          example: https://api.dmwire.ai/v1/channels/whatsapp-web/connect?token=eyJhbGciOi...
        connect_url_expires_at:
          type:
            - integer
            - 'null'
          description: Unix epoch (ms) when connect_url stops working. Start a new connection to get a fresh link.
        poll_qr_path:
          type: string
          description: Relative path to fetch the QR code for this connection (alternative to connect_url for integrations that render the QR themselves).
        poll_status_path:
          type: string
          description: Relative path to poll the connection status.
    WhatsAppWebQrResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+15551230000'
        status:
          type: string
          enum:
            - qr_pending
          example: qr_pending
        qr_code:
          type:
            - string
            - 'null'
          description: The raw QR payload string. Render it as a QR image for the end user to scan.
        qr_data_url:
          type:
            - string
            - 'null'
          description: A data URL of the QR image that can be used directly as an image source.
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
          description: When this QR code expires. Restart the connection if it lapses before scanning.
    WhatsAppWebStatusResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+15551230000'
        status:
          type: string
          description: Current connection state. connected (or open) is the terminal success state; disconnected and not_initialized are terminal failure states; qr_pending and connecting are transitional.
          enum:
            - not_initialized
            - qr_pending
            - connecting
            - connected
            - open
            - disconnected
          example: connected
        has_qr:
          type: boolean
          description: Whether a QR code is currently available to scan.
        qr_expires_at:
          type:
            - string
            - 'null'
          format: date-time
        last_activity:
          type:
            - string
            - 'null'
        message_count:
          type:
            - integer
            - 'null'
        proxy:
          type:
            - string
            - 'null'
        live:
          type: boolean
          description: True when the status was read from the connection service rather than a cached value.
    WhatsAppWebDisconnectResponse:
      type: object
      properties:
        success:
          type: boolean
          example: true
        phone_number:
          type: string
          example: '+15551230000'
        status:
          type: string
          enum:
            - removed
            - disconnected
          example: removed
          description: '"removed" when the number record was deleted from the account (a number you paired yourself).'
    WhatsAppWebError:
      type: object
      properties:
        success:
          type: boolean
          example: false
        error:
          type: string
        error_code:
          type: integer
  parameters:
    ApiKeyParam:
      name: apiKey
      in: query
      description: Your DMWire API key. Alternatively send it as the X-API-Key header or as Authorization Bearer <key>.
      required: false
      schema:
        type: string
      example: your_api_key
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: query
      name: apiKey
      description: Your DMWire API key.
paths:
  /accounts:
    get:
      operationId: list_accounts
      summary: List Connected Accounts
      security:
        - ApiKeyAuth: []
      description: |
        Lists the WhatsApp Web and Telegram accounts connected to your account. status is one of
        connected, connecting, disconnected or restricted. limits shows today's sends and new
        contacts against the caps; ramp_day is how far the account is into its warm-up ramp
        (null when the account has no ramp).
      tags:
        - Accounts
      responses:
        '200':
          description: The connected accounts
          content:
            application/json:
              schema:
                type: object
                properties:
                  accounts:
                    type: array
                    items:
                      $ref: '#/components/schemas/WireAccount'
        '404':
          description: This API is not enabled for the account
      x-scope-tag: dmwire-accounts
  /messages:
    get:
      operationId: list_messages
      summary: List Recent Messages
      security:
        - ApiKeyAuth: []
      description: |
        The most recent messages on your accounts, sent and received, newest first (up to 100 per
        call, 50 by default). Filter by direction or account_id. When next_cursor is not null, pass
        it as before to read the next page. For waiting on NEW messages use wait_for_messages.
      tags:
        - Messages
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
        - name: direction
          in: query
          required: false
          schema:
            type: string
            enum:
              - inbound
              - outbound
        - name: account_id
          in: query
          required: false
          schema:
            type: string
        - name: before
          in: query
          required: false
          description: The next_cursor of the previous page
          schema:
            type: string
      responses:
        '200':
          description: The messages, newest first
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    type: array
                    items:
                      $ref: '#/components/schemas/WireMessage'
                  next_cursor:
                    type: string
                    nullable: true
                    description: Pass as before for the next page; null on the last page
        '400':
          description: Invalid limit, direction or cursor
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
      x-scope-tag: dmwire-messages
    post:
      operationId: send_message
      summary: Send a Message
      security:
        - ApiKeyAuth: []
      description: |
        Queues a text message (optionally with one media URL) from a connected account. Address the
        recipient by to.phone (international format) or to.contact_id. account_id may be omitted
        when exactly one account is connected. On WhatsApp a new phone number creates the contact; on
        Telegram only an existing contact can be messaged. Answers 202 with the message id; read
        get_message for the delivery status.

        Refusals carry error_code: no_connected_account (409), ambiguous_account (400),
        account_not_found (404), contact_not_found (404), telegram_requires_existing_contact
        (422), contact_channel_mismatch (422), contact_do_not_disturb (422), contact_private (422),
        account_suspended (403), loop_guard (429), opener_burst (429), daily_send_cap (429),
        new_contact_cap (429). A 429 carries retry_after_s.
      tags:
        - Messages
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - to
                - text
              properties:
                account_id:
                  type: string
                  description: The account to send from (see list_accounts). Optional when one account is connected.
                to:
                  type: object
                  properties:
                    phone:
                      type: string
                      example: '+31612345678'
                    contact_id:
                      type: string
                text:
                  type: string
                  maxLength: 4096
                media_url:
                  type: string
                  format: uri
                  description: An https URL of an image, video, audio file or document to attach.
      responses:
        '202':
          description: Queued for delivery
          content:
            application/json:
              schema:
                type: object
                properties:
                  message_id:
                    type: string
                  status:
                    type: string
                    enum:
                      - queued
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
        '403':
          description: Account suspended
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
        '409':
          description: No connected account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
        '422':
          description: The contact cannot be messaged
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
        '429':
          description: A daily cap, the loop guard or the burst guard was hit
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
      x-scope-tag: dmwire-messages
  /messages/wait:
    get:
      operationId: wait_for_messages
      summary: Wait for New Messages
      security:
        - ApiKeyAuth: []
      description: |
        Long poll for incoming messages. Returns as soon as at least one message newer than cursor
        arrives (up to 50 per call), or an empty list when timeout_s passes. Always pass the returned
        cursor into the next call; without a cursor the wait starts from now. At most 2 waits may be
        open at once per account (429 wait_concurrency).
      tags:
        - Messages
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          description: The opaque cursor returned by the previous call.
        - name: account_id
          in: query
          required: false
          schema:
            type: string
          description: Only messages received on this account.
        - name: timeout_s
          in: query
          required: false
          schema:
            type: integer
            minimum: 0
            maximum: 55
            default: 25
      responses:
        '200':
          description: New messages (possibly none) and the cursor for the next call
          content:
            application/json:
              schema:
                type: object
                properties:
                  messages:
                    type: array
                    items:
                      $ref: '#/components/schemas/WireMessage'
                  cursor:
                    type: string
        '400':
          description: Invalid cursor or timeout
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
        '429':
          description: Too many concurrent waits
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
      x-scope-tag: dmwire-messages
  /messages/{id}:
    get:
      operationId: get_message
      summary: Get a Message
      security:
        - ApiKeyAuth: []
      description: |
        Reads one message (sent or received) with its current status. Use it after send_message to
        see whether the message was sent, delivered, read or failed.
      tags:
        - Messages
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      responses:
        '200':
          description: The message
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireMessage'
        '404':
          description: No such message on this account
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WireError'
      x-scope-tag: dmwire-messages
  /usage:
    get:
      operationId: get_usage
      summary: Get Today's Usage
      security:
        - ApiKeyAuth: []
      description: |
        Today's sends and new contacts (UTC day) against the plan caps.
      tags:
        - Usage
      responses:
        '200':
          description: Today's usage
          content:
            application/json:
              schema:
                type: object
                properties:
                  plan:
                    type: string
                    example: free
                  day:
                    type: string
                    example: '2026-10-17'
                  sends:
                    type: integer
                  sends_cap:
                    type: integer
                  new_contacts:
                    type: integer
                  new_contacts_cap:
                    type: integer
                  status:
                    type: string
                    enum:
                      - active
                      - suspended
                    description: suspended means outbound is refused until the account is reviewed
                  accounts_total:
                    type: integer
                    description: Accounts added, connected or not
                  accounts_connected:
                    type: integer
                  accounts_cap:
                    type: integer
                    description: Accounts the plan allows
      x-scope-tag: dmwire-usage
  /webhooks:
    get:
      summary: List Webhook Subscriptions
      security:
        - ApiKeyAuth: []
      description: |
        Returns every webhook subscription configured on the account, including the events each one
        listens to. The returned id (or the exact name) can be used as the
        webhookId path parameter in the other webhook endpoints.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
      responses:
        '200':
          description: The account's webhook subscriptions
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhooks:
                    type: array
                    items:
                      $ref: '#/components/schemas/WebhookSubscription'
              example:
                success: true
                webhooks:
                  - id: '0'
                    name: Order updates hook
                    url: https://hooks.example.com/incoming
                    subscribed_to:
                      - message.received
                      - message.sent
                      - message.delivered
                      - message.read
                      - message.failed
                      - account.connected
                      - account.disconnected
                      - account.restricted
                      - account.limit_reached
                    created_at: '2026-06-09T12:00:00.000Z'
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              example:
                success: false
                error_code: 401
                error: Invalid API key
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
      x-scope-tag: Webhooks
      operationId: list_webhooks
    post:
      summary: Create Webhook Subscription
      security:
        - ApiKeyAuth: []
      description: |
        Creates a new webhook subscription. The URL must use HTTPS and be publicly reachable.
        The subscribed_to array selects which event types are delivered to the URL, use
        GET /webhooks/events to discover the valid values. Optionally pass a name so the
        subscription can be addressed by a stable identifier later.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - url
                - subscribed_to
              properties:
                url:
                  type: string
                  description: HTTPS URL that will receive event payloads via POST.
                subscribed_to:
                  type: array
                  description: Event types to subscribe to. Must contain at least one valid event name.
                  items:
                    type: string
                    enum:
                      - message.received
                      - message.sent
                      - message.delivered
                      - message.read
                      - message.failed
                      - account.connected
                      - account.disconnected
                      - account.restricted
                      - account.limit_reached
                name:
                  type: string
                  description: Optional display name. Also usable as the webhookId path parameter. Defaults to a timestamped name.
                retries_enabled:
                  type: boolean
                  description: Retry failed deliveries (1m, 5m, 30m, 2h). Off by default. See the Retries section for the duplicate-delivery caveat.
                enabled:
                  type: boolean
                  description: Account on/off switch for the subscription. Defaults to true (on). Pass false to create it switched off.
                generate_signing_secret:
                  type: boolean
                  description: |
                    When true, an HMAC signing secret is minted for the new subscription (turning signing on)
                    and returned once as a top-level signing_secret field in the response. Store it then, it
                    is never returned in full again by create/list/update; only GET /webhooks/{webhookId}/signing-secret
                    exposes it afterwards. You can also turn signing on later via POST /webhooks/{webhookId}/signing-secret.
            example:
              url: https://hooks.example.com/incoming
              subscribed_to:
                - message.received
                - message.sent
                - message.delivered
                - message.read
                - message.failed
                - account.connected
                - account.disconnected
                - account.restricted
                - account.limit_reached
              name: Order updates hook
      responses:
        '201':
          description: Subscription created
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  signing_secret:
                    type: string
                    description: The newly minted signing secret, returned only when generate_signing_secret was true. Shown once, store it now.
                    examples:
                      - whsec_1a2b3c...
                  webhook:
                    $ref: '#/components/schemas/WebhookSubscription'
              example:
                success: true
                webhook_id: '1'
                webhook:
                  id: '1'
                  name: Order updates hook
                  url: https://hooks.example.com/incoming
                  subscribed_to:
                    - message.received
                    - message.sent
                    - message.delivered
                    - message.read
                    - message.failed
                    - account.connected
                    - account.disconnected
                    - account.restricted
                    - account.limit_reached
                  created_at: '2026-06-09T12:00:00.000Z'
                  enabled: true
                  retries_enabled: false
                  signing_enabled: false
                  signing_secret_created_at: null
        '400':
          description: Validation error (missing url, empty or invalid subscribed_to, or a URL that is not allowed)
          content:
            application/json:
              example:
                success: false
                error: Webhook URL must use https
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
      x-scope-tag: Webhooks
      operationId: create_webhook
  /webhooks/events:
    get:
      summary: List Subscribable Event Types
      security:
        - ApiKeyAuth: []
      description: |
        Returns the full list of event types that webhook subscriptions can listen to. Use these
        exact strings in the subscribed_to field when creating or updating a subscription.
        The events are (message.received, message.sent,
        message.delivered, message.read, message.failed, account.connected, account.disconnected,
        account.restricted, account.limit_reached), plus a descriptions map; subscribing to an event
        outside the account's set returns 400.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
      responses:
        '200':
          description: The valid event types
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  events:
                    type: array
                    items:
                      type: string
                      enum:
                        - message.received
                        - message.sent
                        - message.delivered
                        - message.read
                        - message.failed
                        - account.connected
                        - account.disconnected
                        - account.restricted
                        - account.limit_reached
              example:
                success: true
                events:
                  - message.received
                  - message.sent
                  - message.delivered
                  - message.read
                  - message.failed
                  - account.connected
                  - account.disconnected
                  - account.restricted
                  - account.limit_reached
        '401':
          description: Missing or invalid credentials
          content:
            application/json:
              example:
                success: false
                error_code: 401
                error: Invalid API key
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
      x-scope-tag: Webhooks
      operationId: list_webhook_events
  /webhooks/{webhookId}:
    put:
      summary: Update Webhook Subscription
      security:
        - ApiKeyAuth: []
      description: |
        Updates an existing webhook subscription. Provide at least one of url, subscribed_to or name; omitted fields keep their current values. When the URL changes,
        delivery for the new URL is automatically re-enabled so a previously failing endpoint gets
        a fresh start.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                  description: New HTTPS delivery URL.
                subscribed_to:
                  type: array
                  description: Replacement event list. Must contain at least one valid event name.
                  items:
                    type: string
                    enum:
                      - message.received
                      - message.sent
                      - message.delivered
                      - message.read
                      - message.failed
                      - account.connected
                      - account.disconnected
                      - account.restricted
                      - account.limit_reached
                name:
                  type: string
                  description: New display name.
                retries_enabled:
                  type: boolean
                  description: Turn delivery retries on or off for this subscription.
                enabled:
                  type: boolean
                  description: Account on/off switch. Set false to switch the subscription off (suppress delivery), true to switch it back on. Signing is managed separately via the signing-secret routes, not here.
            example:
              url: https://hooks.example.com/v2/incoming
              subscribed_to:
                - message.received
                - message.sent
                - message.delivered
                - message.read
                - message.failed
                - account.connected
                - account.disconnected
                - account.restricted
                - account.limit_reached
      responses:
        '200':
          description: Subscription updated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  webhook:
                    $ref: '#/components/schemas/WebhookSubscription'
              example:
                success: true
                webhook_id: '0'
                webhook:
                  id: '0'
                  name: Order updates hook
                  url: https://hooks.example.com/v2/incoming
                  subscribed_to:
                    - message.received
                    - message.sent
                    - message.delivered
                    - message.read
                    - message.failed
                    - account.connected
                    - account.disconnected
                    - account.restricted
                    - account.limit_reached
                  created_at: '2026-06-09T12:00:00.000Z'
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: update_webhook
    delete:
      summary: Delete Webhook Subscription
      security:
        - ApiKeyAuth: []
      description: |
        Removes a webhook subscription so its URL stops receiving event payloads. Delivery-health
        counters for the URL are reset, so re-adding the same URL later starts with a clean record.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      responses:
        '200':
          description: Subscription deleted
          content:
            application/json:
              example:
                success: true
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: delete_webhook
  /webhooks/{webhookId}/test:
    post:
      summary: Send Test Payload
      security:
        - ApiKeyAuth: []
      description: |
        Sends a sample payload to the subscription's URL so you can verify your receiver end-to-end.
        Optionally pass an event to control which event type the sample payload simulates. Test
        deliveries never affect the subscription's health counters. The response reports whether the
        delivery succeeded; a failed test returns delivered:false together with the failure details
        instead of an error status.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                event:
                  type: string
                  description: Event type to simulate. Must be one of the values from GET /webhooks/events. Defaults to a delivery event.
            example:
              event: message.received
      responses:
        '200':
          description: Test attempted, check the delivered flag for the outcome
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  delivered:
                    type: boolean
                    description: True when the receiver accepted the test payload.
                  failure_type:
                    type: string
                    description: Present when delivered is false. One of permanent, temporary, timeout, network, unknown.
                  status_code:
                    type:
                      - integer
                      - 'null'
                    description: HTTP status code returned by the receiver when delivered is false, if available.
                  error_message:
                    type: string
                    description: Error message from the failed delivery attempt, when delivered is false.
              examples:
                delivered:
                  summary: Receiver accepted the payload
                  value:
                    success: true
                    webhook_id: '0'
                    delivered: true
                failed:
                  summary: Receiver rejected the payload
                  value:
                    success: true
                    webhook_id: '0'
                    delivered: false
                    failure_type: permanent
                    status_code: 404
                    error_message: Request failed with status code 404
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: test_webhook
  /webhooks/{webhookId}/health:
    get:
      summary: Get Webhook Delivery Health
      security:
        - ApiKeyAuth: []
      description: |
        Returns the delivery-health record for the subscription's URL: how many deliveries have
        succeeded and failed, whether delivery is currently paused after repeated failures, and the
        details of the most recent failure. Returns health:null when no deliveries have been
        attempted yet.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      responses:
        '200':
          description: The delivery-health record for the subscription's URL
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  url:
                    type: string
                  health:
                    oneOf:
                      - $ref: '#/components/schemas/WebhookHealthStatus'
                      - type: 'null'
              example:
                success: true
                webhook_id: '0'
                url: https://hooks.example.com/incoming
                health:
                  consecutive_failures: 0
                  total_failures: 2
                  total_successes: 120
                  is_disabled: false
                  disabled_at: null
                  disabled_reason: null
                  last_failure: null
                  last_success_at: '2026-06-09T12:00:00.000Z'
                  created_at: '2026-05-01T08:00:00.000Z'
                  updated_at: '2026-06-09T12:00:00.000Z'
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: get_webhook_health
  /webhooks/{webhookId}/reenable:
    post:
      summary: Re-enable Webhook Delivery
      security:
        - ApiKeyAuth: []
      description: |
        Resumes delivery for a webhook whose URL was paused automatically after repeated failures.
        Resets the paused flag and failure counters. No delivery attempt is made, use the test
        endpoint afterwards to confirm the receiver is healthy again.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      responses:
        '200':
          description: Delivery re-enabled
          content:
            application/json:
              example:
                success: true
                webhook_id: '0'
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: reenable_webhook
  /webhooks/{webhookId}/signing-secret:
    get:
      summary: Read Webhook Signing Secret
      security:
        - ApiKeyAuth: []
      description: |
        Returns the subscription's HMAC signing secret so you can configure signature verification on
        your receiver. The secret is symmetric, we hold the same value your endpoint needs, so it is
        readable rather than write-once. When signing is off, signing_enabled is false and signing_secret
        is null.

        Signed deliveries carry an `X-Webhook-Signature` header (`v1=<hex>`), an HMAC-SHA256 of
        `<X-Webhook-Timestamp>.<raw request body>` keyed with this secret. Verify against the raw
        body, reject stale timestamps, and compare in constant time.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      responses:
        '200':
          description: The subscription's signing state
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  signing_enabled:
                    type: boolean
                  signing_secret:
                    type:
                      - string
                      - 'null'
                    description: The HMAC signing secret, or null when signing is off.
                  signing_secret_created_at:
                    type:
                      - string
                      - 'null'
                    format: date-time
              examples:
                'on':
                  summary: Signing is on
                  value:
                    success: true
                    webhook_id: '0'
                    signing_enabled: true
                    signing_secret: whsec_1a2b3c...
                    signing_secret_created_at: '2026-07-15T09:30:00.000Z'
                'off':
                  summary: Signing is off
                  value:
                    success: true
                    webhook_id: '0'
                    signing_enabled: false
                    signing_secret: null
                    signing_secret_created_at: null
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: get_webhook_signing_secret
    post:
      summary: Generate or Rotate Webhook Signing Secret
      security:
        - ApiKeyAuth: []
      description: |
        Mints a new signing secret for the subscription, or replaces the existing one. Creating a secret
        is how signing is turned on. The new secret is returned in the response.

        Rotation is a hard cutover, not a grace period: the very next delivery is signed with the new
        secret only. When rotating a live endpoint, accept both the old and new secret briefly so
        deliveries in flight during the change still verify.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      responses:
        '200':
          description: Signing secret generated or rotated
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  signing_enabled:
                    type: boolean
                  signing_secret:
                    type: string
                    description: The newly generated signing secret.
                  signing_secret_created_at:
                    type:
                      - string
                      - 'null'
                    format: date-time
              example:
                success: true
                webhook_id: '0'
                signing_enabled: true
                signing_secret: whsec_9f8e7d...
                signing_secret_created_at: '2026-07-15T10:00:00.000Z'
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: rotate_webhook_signing_secret
    delete:
      summary: Turn Off Webhook Signing
      security:
        - ApiKeyAuth: []
      description: |
        Removes the subscription's signing secret, turning signing off. Subsequent deliveries carry no
        signature headers, exactly as the webhook behaved before signing was enabled.
      tags:
        - Webhooks
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: webhookId
          in: path
          required: true
          description: The subscription id (from the id field) or its exact name.
          schema:
            type: string
      responses:
        '200':
          description: Signing turned off
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  webhook_id:
                    type: string
                  signing_enabled:
                    type: boolean
              example:
                success: true
                webhook_id: '0'
                signing_enabled: false
        '403':
          description: Webhooks are not enabled for this account
          content:
            application/json:
              example:
                success: false
                error: Webhooks are not enabled for this account
        '404':
          description: No subscription with that id or name exists on this account
          content:
            application/json:
              example:
                success: false
                error: Webhook not found
      x-scope-tag: Webhooks
      operationId: turn_off_webhook_signing
  /channels/telegram/connect:
    post:
      security:
        - ApiKeyAuth: []
      summary: Start a connection session
      description: Begins a connection session for an account phone number. In code mode the connection service sends a one-time login code to the account and reports code_required; in qr mode it returns a login token and QR URL to display. Poll the status endpoint until the channel reports connected.
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TelegramConnectRequest'
      responses:
        '200':
          description: Session started.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramConnectResponse'
        '400':
          description: Invalid or missing request fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: This channel is not enabled for the account, or the plan lacks a channels tier.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: This account is already connected elsewhere.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-scope-tag: Telegram Connection
      operationId: connect_telegram
  /channels/telegram/connect/{phoneNumber}/verify-code:
    post:
      security:
        - ApiKeyAuth: []
      summary: Submit the login code
      description: Submits the one-time login code for a pending session. On success the status becomes connected; when the account has two-factor enabled the status becomes password_required and the password must be submitted next.
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The account phone number being connected, in E.164 format.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TelegramVerifyCodeRequest'
      responses:
        '200':
          description: Code accepted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramVerifyResponse'
        '400':
          description: Missing or invalid login code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: This channel is not enabled for the account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-scope-tag: Telegram Connection
      operationId: submit_telegram_code
  /channels/telegram/connect/{phoneNumber}/verify-password:
    post:
      security:
        - ApiKeyAuth: []
      summary: Submit the two-factor password
      description: Submits the two-factor password for a session that reported password_required. On success the status becomes connected and the channel is live.
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The account phone number being connected, in E.164 format.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TelegramVerifyPasswordRequest'
      responses:
        '200':
          description: Password accepted.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramVerifyResponse'
        '400':
          description: Missing or invalid password.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: This channel is not enabled for the account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-scope-tag: Telegram Connection
      operationId: submit_telegram_password
  /channels/telegram/connect/{phoneNumber}/status:
    get:
      security:
        - ApiKeyAuth: []
      summary: Get live connection status
      description: Returns the live connection status for a session, polled from the connection service. Poll this until the status is connected or an error/disconnected status. Reports not_initialized when no session exists.
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The account phone number, in E.164 format.
          schema:
            type: string
      responses:
        '200':
          description: Current connection status.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramStatusResponse'
        '404':
          description: No connection record exists for this phone number.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-scope-tag: Telegram Connection
      operationId: get_telegram_status
  /channels/telegram/{phoneNumber}:
    delete:
      security:
        - ApiKeyAuth: []
      summary: Disconnect the channel
      description: 'Tears down the connection session and removes the account record. Idempotent: the record is removed even when the connection service is unreachable, so repeated calls succeed.'
      tags:
        - Accounts
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The account phone number to disconnect, in E.164 format.
          schema:
            type: string
      responses:
        '200':
          description: Channel removed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TelegramDisconnectResponse'
        '404':
          description: No connection record exists for this phone number.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      x-scope-tag: Telegram Connection
      operationId: disconnect_telegram
  /channels/whatsapp-web/connections:
    post:
      security:
        - ApiKeyAuth: []
      tags:
        - Accounts
      summary: Start a WhatsApp Web pairing session
      description: Begins pairing a WhatsApp number by QR code. Creates or resets the connection and returns a session whose QR code you then fetch and have the end user scan. Poll the status endpoint until the connection reports connected.
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WhatsAppWebConnectRequest'
      responses:
        '200':
          description: Pairing session started.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebConnectResponse'
        '400':
          description: Missing or invalid request fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '401':
          description: Authentication required or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '403':
          description: The account's plan does not include channel connections.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '404':
          description: The referenced account could not be found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '409':
          description: This number is already connected.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '503':
          description: The connection service is temporarily at capacity.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
      x-scope-tag: WhatsApp Web Connections
      operationId: connect_whatsapp
  /channels/whatsapp-web/connections/{phoneNumber}/qr:
    get:
      security:
        - ApiKeyAuth: []
      tags:
        - Accounts
      summary: Get the pairing QR code
      description: Returns the current QR code for a pairing session so it can be rendered for the end user to scan. The code is short-lived; poll this endpoint every 10 to 15 seconds until the status reports connected, and restart the connection if the code expires.
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The connected number in E.164 format.
          schema:
            type: string
          example: '+15551230000'
      responses:
        '200':
          description: QR code returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebQrResponse'
        '400':
          description: This number cannot be paired with WhatsApp Web.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '401':
          description: Authentication required or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '404':
          description: The connection was not found, or the QR code is not ready yet.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '410':
          description: The QR code expired. Restart the connection to generate a new one.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '503':
          description: The QR service is temporarily unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
      x-scope-tag: WhatsApp Web Connections
      operationId: get_whatsapp_qr
  /channels/whatsapp-web/connections/{phoneNumber}/status:
    get:
      security:
        - ApiKeyAuth: []
      tags:
        - Accounts
      summary: Get the connection status
      description: Returns the live connection status for a pairing session. The terminal success state is connected (the service may also report open). Treat disconnected and not_initialized as terminal failure states. Poll this endpoint after the end user scans the QR code to confirm the connection.
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The connected number in E.164 format.
          schema:
            type: string
          example: '+15551230000'
      responses:
        '200':
          description: Connection status returned.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebStatusResponse'
        '401':
          description: Authentication required or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '404':
          description: The connection was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '502':
          description: The connection service could not be reached.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
      x-scope-tag: WhatsApp Web Connections
      operationId: get_whatsapp_status
  /channels/whatsapp-web/connections/{phoneNumber}:
    delete:
      security:
        - ApiKeyAuth: []
      tags:
        - Accounts
      summary: Disconnect a WhatsApp Web connection
      description: Disconnects the pairing session and removes the connection record. The operation is idempotent and always succeeds locally even if the connection service is unreachable.
      parameters:
        - $ref: '#/components/parameters/ApiKeyParam'
        - name: phoneNumber
          in: path
          required: true
          description: The connected number in E.164 format.
          schema:
            type: string
          example: '+15551230000'
      responses:
        '200':
          description: Disconnected. status is "removed" when the number was deleted from the account.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebDisconnectResponse'
        '401':
          description: Authentication required or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
        '404':
          description: The connection was not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WhatsAppWebError'
      x-scope-tag: WhatsApp Web Connections
      operationId: disconnect_whatsapp
