openapi: 3.1.0
info:
  title: Kapso Meta Proxy API
  version: 1.0.0
  description: |
    Kapso's Meta Proxy API provides a unified interface to WhatsApp Business Platform with enhanced features and Kapso-specific extensions.

    This API acts as a proxy layer between your application and WhatsApp, adding:
    - Simplified authentication with project-level API keys
    - Enhanced message metadata and tracking
    - Conversation management capabilities
    - Voice call integration
    - Extended contact and template management

    ## Base URL

    All API requests are made to: `https://api.kapso.ai/meta/whatsapp/v24.0`

    ## Authentication

    The API supports authentication via **X-API-Key header** (recommended):

    ```
    X-API-Key: your_project_api_key
    ```

    Alternative: Bearer token authentication is also supported for backward compatibility:

    ```
    Authorization: Bearer your_access_token
    ```

    Note: X-API-Key is the recommended authentication method for the Meta Proxy API.
  contact:
    name: Kapso Support
    url: https://kapso.ai
    email: dev@kap.so
servers:
  - url: https://api.kapso.ai/meta/whatsapp/v24.0
    description: Production server
security:
  - ApiKeyAuth: []
  - BearerAuth: []
tags:
  - name: Messages
    description: Send and retrieve WhatsApp messages
  - name: Conversations
    description: Manage WhatsApp conversations
  - name: Contacts
    description: Manage WhatsApp contacts
  - name: Templates
    description: Manage message templates
  - name: Media
    description: Upload and retrieve media files
  - name: Calls
    description: Manage voice calls
  - name: Settings
    description: Account settings and configuration
  - name: Business Profile
    description: Business profile management
  - name: Phone Numbers
    description: Phone number management
  - name: Flows
    description: WhatsApp Flow management (Beta)
  - name: Block Users
    description: Block and unblock WhatsApp users
  - name: Usernames
    description: Reserve and manage WhatsApp business usernames
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: |
        Project API key for authentication. This is the recommended authentication method.

        Get your API key from the Kapso dashboard under Integrations > API keys.
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        Bearer token authentication (alternative method).

        Note: X-API-Key authentication is recommended for the Meta Proxy API.
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - message
            - type
            - code
          properties:
            message:
              type: string
              description: Human-readable error message
              example: Invalid phone number format
            type:
              type: string
              description: Error category
              example: OAuthException
            code:
              type: integer
              description: Error code
              example: 400
            error_subcode:
              type: integer
              description: More specific error code
              example: 1001
            fbtrace_id:
              type: string
              description: Facebook trace ID for debugging
              example: AXk7s_8dR4eVHp9Kq2MmNlO
    MarketingPreferenceStoppedError:
      type: object
      description: Returned when the recipient asked WhatsApp to stop marketing
        messages from this number. The send is refused before reaching Meta and
        is not charged. Do not retry — use a utility or authentication
        template, or another number.
      required:
        - error
        - code
      properties:
        error:
          type: string
          description: Human-readable error message
          example: Contact stopped marketing messages on this WhatsApp number
        code:
          type: string
          enum:
            - marketing_preference_stopped
    PaginationCursor:
      type: object
      properties:
        before:
          type: string
          description: Cursor for previous page (Base64 encoded)
          example: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
        after:
          type: string
          description: Cursor for next page (Base64 encoded)
          example: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNFQwOToyMTozMi43ODkwMTJaIiwiMTIzMjAiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
    Paging:
      type: object
      properties:
        cursors:
          $ref: "#/components/schemas/PaginationCursor"
    WhatsappContact:
      type: object
      required:
        - id
      properties:
        id:
          type: string
          description: Contact ID (UUID)
          example: 123e4567-e89b-12d3-a456-426614174000
        wa_id:
          type: string
          nullable: true
          description: WhatsApp ID (phone number). Can be null when Meta only provides BSUID-based identity.
          example: "15551234567"
        business_scoped_user_id:
          type: string
          nullable: true
          description: WhatsApp business-scoped user ID
          example: US.13491208655302741918
        parent_business_scoped_user_id:
          type: string
          nullable: true
          description: Parent business-scoped user ID when provided by Meta
          example: US.ENT.506847293015824
        username:
          type: string
          nullable: true
          description: WhatsApp username when available
          example: "@testusername"
        profile_name:
          type: string
          description: WhatsApp profile name
          example: John Doe
        display_name:
          type: string
          description: Custom display name
          example: John (VIP Customer)
        metadata:
          type: object
          description: Custom metadata
          additionalProperties: true
          nullable: true
        created_at:
          type: string
          format: date-time
          description: Contact creation timestamp
          example: 2024-01-15T12:34:56.123456Z
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp
          example: 2024-01-15T12:34:56.123456Z
    MessageType:
      type: string
      enum:
        - text
        - image
        - video
        - audio
        - document
        - sticker
        - location
        - contacts
        - interactive
        - template
        - reaction
      description: Type of WhatsApp message
    TextMessage:
      type: object
      required:
        - body
      properties:
        body:
          type: string
          description: Text content of the message
          example: Hello! How can I help you today?
        preview_url:
          type: boolean
          description: Whether to show URL preview (defaults to false if omitted)
          example: true
    MediaMessage:
      type: object
      properties:
        id:
          type: string
          description: |-
            Media ID from WhatsApp (uploaded media).
            Recommended over `link` for better performance.
          example: abc123def456
        link:
          type: string
          format: uri
          description: |-
            Public URL to media file (hosted media).
            Using uploaded media with `id` is recommended for better performance.
          example: https://example.com/image.jpg
        caption:
          type: string
          description: |-
            Media caption text.
            - Images: max 1024 characters
            - Videos: max 1024 characters
            - Documents: max 1024 characters

            Not supported for stickers or audio.
          maxLength: 1024
          example: Check out this photo!
        filename:
          type: string
          description: |-
            Filename with extension (for documents only).
            WhatsApp client displays appropriate file type icon based on extension.
          example: report.pdf
    AudioMessage:
      type: object
      properties:
        id:
          type: string
          description: Media ID from WhatsApp (uploaded media)
          example: abc123def456
        link:
          type: string
          format: uri
          description: |-
            Public URL to audio file (hosted media).
            Using uploaded media with `id` is recommended for better performance.
          example: https://example.com/audio.mp3
        voice:
          type: boolean
          description: |-
            Set to `true` for voice messages (voice notes with transcription support).
            Voice messages must be .ogg files encoded with OPUS codec.
            Set to `false` or omit for basic audio messages.

            Voice messages include: automatic download, profile picture, voice icon, and optional transcription.
            Basic audio messages display a download icon and music icon.
          example: true
    StickerMessage:
      type: object
      properties:
        id:
          type: string
          description: Media ID from WhatsApp
          example: abc123def456
        link:
          type: string
          format: uri
          description: Public URL to sticker file
          example: https://example.com/sticker.webp
        mime_type:
          type: string
          description: MIME type of the sticker
          example: image/webp
        animated:
          type: boolean
          description: Whether the sticker is animated
          example: false
    OrderMessage:
      type: object
      properties:
        catalog_id:
          type: string
          description: Catalog ID
          example: cat_12345
        product_items:
          type: array
          description: Array of product items
          items:
            type: object
        order_text:
          type: string
          description: Order text
          example: I'd like to order this item
    SupportedDocumentFormats:
      description: |-
        Supported document formats for document messages.

        | Format | Extension | MIME Type | Max Size |
        |--------|-----------|-----------|----------|
        | Text | .txt | text/plain | 100 MB |
        | Microsoft Excel | .xls | application/vnd.ms-excel | 100 MB |
        | Microsoft Excel | .xlsx | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet | 100 MB |
        | Microsoft Word | .doc | application/msword | 100 MB |
        | Microsoft Word | .docx | application/vnd.openxmlformats-officedocument.wordprocessingml.document | 100 MB |
        | Microsoft PowerPoint | .ppt | application/vnd.ms-powerpoint | 100 MB |
        | Microsoft PowerPoint | .pptx | application/vnd.openxmlformats-officedocument.presentationml.presentation | 100 MB |
        | PDF | .pdf | application/pdf | 100 MB |
      type: object
    SupportedImageFormats:
      description: |-
        Supported image formats for image messages.
        Images must be 8-bit, RGB or RGBA.

        | Format | Extension | MIME Type | Max Size |
        |--------|-----------|-----------|----------|
        | JPEG | .jpeg, .jpg | image/jpeg | 5 MB |
        | PNG | .png | image/png | 5 MB |
      type: object
    SupportedVideoFormats:
      description: |-
        Supported video formats for video messages.
        Only H.264 video codec and AAC audio codec supported.
        Single audio stream or no audio stream only.

        | Format | Extension | MIME Type | Max Size |
        |--------|-----------|-----------|----------|
        | 3GPP | .3gp | video/3gpp | 16 MB |
        | MP4 | .mp4 | video/mp4 | 16 MB |
      type: object
    SupportedAudioFormats:
      description: |-
        Supported audio formats for audio messages.
        Voice messages (voice=true) require .ogg files with OPUS codec.

        | Format | Extension | MIME Type | Max Size |
        |--------|-----------|-----------|----------|
        | AAC | .aac | audio/aac | 16 MB |
        | AMR | .amr | audio/amr | 16 MB |
        | MP3 | .mp3 | audio/mpeg | 16 MB |
        | MP4 Audio | .m4a | audio/mp4 | 16 MB |
        | OGG Audio | .ogg | audio/ogg (OPUS codec only) | 16 MB |
      type: object
    SupportedStickerFormats:
      description: |-
        Supported sticker formats for sticker messages.

        | Type | Extension | MIME Type | Max Size |
        |------|-----------|-----------|----------|
        | Static | .webp | image/webp | 100 KB |
        | Animated | .webp | image/webp | 500 KB |
      type: object
    LocationMessage:
      type: object
      required:
        - latitude
        - longitude
      properties:
        latitude:
          type: number
          format: double
          description: Latitude coordinate
          example: 37.7749
        longitude:
          type: number
          format: double
          description: Longitude coordinate
          example: -122.4194
        name:
          type: string
          description: Location name
          example: Golden Gate Bridge
        address:
          type: string
          description: Location address
          example: San Francisco, CA
    ContactCard:
      type: object
      required:
        - name
      properties:
        addresses:
          type: array
          description: Physical addresses for the contact
          items:
            type: object
            properties:
              street:
                type: string
                description: Street number and name
                example: 1 Lucky Shrub Way
              city:
                type: string
                description: City name
                example: Menlo Park
              state:
                type: string
                description: State abbreviation or full name
                example: CA
              zip:
                type: string
                description: ZIP or postal code
                example: "94025"
              country:
                type: string
                description: Full country name
                example: United States
              country_code:
                type: string
                description: Two-letter country code (ISO 3166-1 alpha-2)
                example: US
              type:
                type: string
                description: Address type (HOME, WORK, etc.)
                example: WORK
        birthday:
          type: string
          format: date
          description: Contact's birthday in YYYY-MM-DD format
          example: 1999-01-23
        emails:
          type: array
          items:
            type: object
            properties:
              email:
                type: string
                example: john@example.com
              type:
                type: string
                example: WORK
        name:
          type: object
          required:
            - formatted_name
          properties:
            formatted_name:
              type: string
              description: Full formatted name (appears in message)
              maxLength: 200
              example: Barbara J. Johnson
            first_name:
              type: string
              description: First name
              example: Barbara
            last_name:
              type: string
              description: Last name
              example: Johnson
            middle_name:
              type: string
              description: Middle name
              example: Joana
            suffix:
              type: string
              description: Name suffix (Jr., Sr., etc.)
              example: Esq.
            prefix:
              type: string
              description: Name prefix (Dr., Mr., Ms., etc.)
              example: Dr.
        org:
          type: object
          description: Organization information
          properties:
            company:
              type: string
              description: Company name
              example: Lucky Shrub
            department:
              type: string
              description: Department name
              example: Legal
            title:
              type: string
              description: Job title
              example: Lead Counsel
        phones:
          type: array
          items:
            type: object
            properties:
              phone:
                type: string
                description: Phone number
                example: "+15551234567"
              type:
                type: string
                description: Phone type (MOBILE, HOME, WORK, etc.)
                example: MOBILE
              wa_id:
                type: string
                description: |-
                  WhatsApp ID for this phone number.
                  If omitted, message will display "Invite to WhatsApp" button instead of "Message" button.
                example: "15551234567"
        urls:
          type: array
          description: Website URLs associated with the contact
          items:
            type: object
            properties:
              url:
                type: string
                format: uri
                description: Website URL
                example: https://www.luckyshrub.com
              type:
                type: string
                description: Website type (WORK, HOME, etc.)
                example: WORK
    InteractiveMessage:
      type: object
      required:
        - type
        - action
      properties:
        type:
          type: string
          enum:
            - button
            - list
            - flow
            - cta_url
            - carousel
            - location_request_message
            - request_contact_info
            - address_message
            - order_details
            - order_status
            - product
            - product_list
            - call_permission_request
            - catalog_message
          description: |-
            Interactive message type:
            - button: Reply buttons (up to 3)
            - list: List picker (up to 10 rows across sections)
            - flow: WhatsApp Flow integration
            - cta_url: Call-to-action URL button
            - carousel: Free-form media carousel with 2-10 cards
            - location_request_message: Request user's location
            - request_contact_info: Request user's phone number and contact info
            - address_message: Address collection (India only)
            - order_details: Order for the user to review and pay (Brazil Pix)
            - order_status: Status update for a previously sent order
            - product: Single product message
            - product_list: Multi-product message (up to 30 products)
            - call_permission_request: Request permission to call
            - catalog_message: Browse full catalog
        body:
          type: object
          description: |-
            Message body text.
            Required for all types except location_request_message (where it's optional).
          required:
            - text
          properties:
            text:
              type: string
              description: Body text (supports URLs and markdown)
              maxLength: 1024
              example: Please select an option
        header:
          type: object
          properties:
            type:
              type: string
              enum:
                - text
                - image
                - video
                - document
            text:
              type: string
              maxLength: 60
            image:
              $ref: "#/components/schemas/MediaMessage"
            video:
              $ref: "#/components/schemas/MediaMessage"
            document:
              $ref: "#/components/schemas/MediaMessage"
        footer:
          type: object
          properties:
            text:
              type: string
              description: Footer text
              maxLength: 60
              example: Powered by Kapso
        action:
          type: object
          description: |-
            Action definition. Structure varies by interactive type.

            NOTE: The structure of the action object varies by type:
            - type=button: Requires `buttons` array
            - type=list: Requires `button` (string) and `sections` array
            - type=flow: Requires `name="flow"` and `parameters` with flow config
            - type=cta_url: Requires `name="cta_url"` and `parameters` with display_text and url
            - type=carousel: Requires `cards` array with 2-10 media cards. Top-level header/footer are not supported.
            - type=location_request_message: Requires `name="send_location"`
            - type=request_contact_info: Requires `name="request_contact_info"`
            - type=address_message: Requires `name="address_message"` and `parameters` with country
            - type=order_details: Requires `name="review_and_pay"` and a `parameters` object
            - type=order_status: Requires `name="review_order"` and a `parameters` object
          properties:
            buttons:
              type: array
              description: |-
                Reply buttons (for type=button).
                Minimum 1, maximum 3 buttons.
              maxItems: 3
              items:
                type: object
                required:
                  - type
                  - reply
                properties:
                  type:
                    type: string
                    enum:
                      - reply
                  reply:
                    type: object
                    required:
                      - id
                      - title
                    properties:
                      id:
                        type: string
                        description: Unique button identifier
                        maxLength: 256
                        example: button_1
                      title:
                        type: string
                        description: Button label text
                        maxLength: 20
                        example: Yes
            button:
              type: string
              description: |-
                Button label for list picker (for type=list).
                When tapped, displays the list modal.
              maxLength: 20
              example: View Options
            sections:
              type: array
              description: |-
                List sections (for type=list).
                Maximum 10 sections, maximum 10 rows total across all sections.
              maxItems: 10
              items:
                type: object
                required:
                  - rows
                properties:
                  title:
                    type: string
                    description: Section title
                    maxLength: 24
                    example: Popular Items
                  rows:
                    type: array
                    description: Rows within this section
                    items:
                      type: object
                      required:
                        - id
                        - title
                      properties:
                        id:
                          type: string
                          description: Unique row identifier (returned in webhook)
                          maxLength: 200
                          example: row_1
                        title:
                          type: string
                          description: Row title
                          maxLength: 24
                          example: Option 1
                        description:
                          type: string
                          description: Row description
                          maxLength: 72
                          example: This is option 1
            cards:
              type: array
              minItems: 2
              maxItems: 10
              description: |-
                Carousel cards (for type=carousel). Each card must include a media header
                with image or video and all cards must use the same button structure:
                either one CTA URL button per card, or the same number of quick-reply
                buttons per card.
              items:
                type: object
                required:
                  - card_index
                  - header
                  - action
                properties:
                  card_index:
                    type: integer
                    minimum: 0
                    description: Zero-based card index. Values should be sequential.
                  type:
                    type: string
                    description: Meta examples use `cta_url` for carousel cards.
                    example: cta_url
                  header:
                    type: object
                    required:
                      - type
                    properties:
                      type:
                        type: string
                        enum:
                          - image
                          - video
                      image:
                        $ref: "#/components/schemas/MediaMessage"
                      video:
                        $ref: "#/components/schemas/MediaMessage"
                  body:
                    type: object
                    properties:
                      text:
                        type: string
                        maxLength: 160
                        description: Optional card body text. Maximum 2 line breaks.
                  action:
                    type: object
                    properties:
                      name:
                        type: string
                        enum:
                          - cta_url
                      parameters:
                        type: object
                        properties:
                          display_text:
                            type: string
                            maxLength: 20
                          url:
                            type: string
                            format: uri
                      buttons:
                        type: array
                        items:
                          type: object
                          required:
                            - type
                            - quick_reply
                          properties:
                            type:
                              type: string
                              enum:
                                - quick_reply
                            quick_reply:
                              type: object
                              required:
                                - id
                                - title
                              properties:
                                id:
                                  type: string
                                  maxLength: 256
                                title:
                                  type: string
                                  maxLength: 20
            name:
              type: string
              description: |-
                Action name.
                - "cta_url" for CTA URL buttons
                - "send_location" for location requests
                - "request_contact_info" for phone number/contact info requests
                - "address_message" for address collection
                - "flow" for WhatsApp Flows
                - "call_permission_request" for call permission request
                - "catalog_message" for catalog browse
              enum:
                - cta_url
                - send_location
                - request_contact_info
                - address_message
                - flow
                - call_permission_request
                - catalog_message
              example: cta_url
            parameters:
              type: object
              description: Parameters object (structure varies by action name).
              properties:
                display_text:
                  type: string
                  description: Button label text (for cta_url)
                  maxLength: 20
                  example: Visit Website
                url:
                  type: string
                  format: uri
                  description: URL to open (for cta_url)
                  example: https://example.com/product?id=123
                country:
                  type: string
                  description: |-
                    Country code (for address_message).
                    Currently only "IN" (India) is supported.
                  example: IN
                values:
                  type: object
                  description: Pre-filled address values (for address_message)
                  properties:
                    name:
                      type: string
                      example: John Doe
                    phone_number:
                      type: string
                      example: "+919876543210"
                    in_pin_code:
                      type: string
                      maxLength: 6
                      example: "400063"
                    house_number:
                      type: string
                      example: "123"
                    floor_number:
                      type: string
                      example: "5"
                    tower_number:
                      type: string
                      example: A
                    building_name:
                      type: string
                      example: Acme Apartments
                    address:
                      type: string
                      example: MG Road
                    landmark_area:
                      type: string
                      example: Near Station
                    city:
                      type: string
                      example: Mumbai
                    state:
                      type: string
                      example: Maharashtra
                saved_addresses:
                  type: array
                  description: Previously saved addresses for selection (for address_message)
                  items:
                    type: object
                    required:
                      - id
                      - value
                    properties:
                      id:
                        type: string
                        example: addr_1
                      value:
                        type: object
                        description: Address details (same structure as values object)
                        additionalProperties: true
                validation_errors:
                  type: object
                  description: Field validation errors to display (for address_message)
                  additionalProperties:
                    type: string
                  example:
                    in_pin_code: Invalid PIN code
                flow_message_version:
                  type: string
                  description: Flow message version (for flow). Must be "3".
                  example: "3"
                flow_id:
                  type: string
                  description: WhatsApp Flow ID (for flow). Cannot use with flow_name.
                  example: "123456789"
                flow_name:
                  type: string
                  description: Flow name (for flow). Cannot use with flow_id.
                  example: Product Survey
                flow_cta:
                  type: string
                  description: Flow CTA button text (for flow)
                  maxLength: 30
                  example: Take Survey
                mode:
                  type: string
                  enum:
                    - draft
                    - published
                  description: Flow mode (for flow, defaults to published if omitted)
                flow_token:
                  type: string
                  description: Flow token for identification (for flow)
                  example: AQAAAAACS5FpgQ_cAAAAAD0QI3s.
                flow_action:
                  type: string
                  enum:
                    - navigate
                    - data_exchange
                  description: Flow action type (for flow, defaults to navigate if omitted)
                flow_action_payload:
                  type: object
                  description: Flow action payload (for flow)
                  properties:
                    screen:
                      type: string
                      description: First screen ID
                      example: WELCOME_SCREEN
                    data:
                      type: object
                      description: Initial data for first screen
                      additionalProperties: true
                catalog_id:
                  type: string
                  description: Catalog ID (for product/product_list)
                product_retailer_id:
                  type: string
                  description: Product ID in the catalog (for product)
                sections:
                  type: array
                  description: "Sections for multi-product messages (product_list). Up to 10 sections. Global limit: ≤ 30 products across all sections."
                  items:
                    type: object
                    required:
                      - title
                      - product_items
                    properties:
                      title:
                        type: string
                        maxLength: 24
                      product_items:
                        type: array
                        items:
                          type: object
                          required:
                            - product_retailer_id
                          properties:
                            product_retailer_id:
                              type: string
                thumbnail_product_retailer_id:
                  type: string
                  description: Thumbnail product to highlight (for catalog_message)
    TemplateMessage:
      type: object
      required:
        - name
        - language
      properties:
        name:
          type: string
          description: Template name
          example: hello_world
        language:
          type: object
          required:
            - code
          properties:
            code:
              type: string
              description: Language code
              example: en_US
        components:
          type: array
          description: Template components with parameters
          items:
            type: object
    ReactionMessage:
      type: object
      required:
        - message_id
        - emoji
      properties:
        message_id:
          type: string
          description: ID of message to react to
          example: wamid.HBgNMTU1NTE...
        emoji:
          type: string
          description: Emoji to react with
          example: 👍
    WhatsappMessage:
      type: object
      required:
        - messaging_product
        - type
      anyOf:
        - required:
            - to
        - required:
            - recipient
      properties:
        messaging_product:
          type: string
          enum:
            - whatsapp
          description: Always "whatsapp"
          example: whatsapp
        recipient_type:
          type: string
          enum:
            - individual
            - group
          default: individual
          description: |-
            Recipient type. Use `individual` for 1:1, `group` for group messages.
            When `group`, `to` must be a Group ID obtained via the Groups API.
        biz_opaque_callback_data:
          type: string
          maxLength: 512
          description: Arbitrary string for tracking (echoed in webhooks)
        to:
          type: string
          description: Recipient phone number or group ID. Use `recipient` for BSUID sends.
          example: "15551234567"
        recipient:
          type: string
          description: Recipient BSUID or parent BSUID. If `to` is also present, the phone number in `to` takes precedence.
          example: US.13491208655302741918
        type:
          $ref: "#/components/schemas/MessageType"
        context:
          type: object
          description: Reply context
          properties:
            message_id:
              type: string
              description: ID of message being replied to
              example: wamid.HBgNMTU1NTE...
        text:
          $ref: "#/components/schemas/TextMessage"
        image:
          $ref: "#/components/schemas/MediaMessage"
        video:
          $ref: "#/components/schemas/MediaMessage"
        audio:
          $ref: "#/components/schemas/AudioMessage"
        document:
          $ref: "#/components/schemas/MediaMessage"
        sticker:
          $ref: "#/components/schemas/MediaMessage"
        location:
          $ref: "#/components/schemas/LocationMessage"
        contacts:
          type: array
          items:
            $ref: "#/components/schemas/ContactCard"
        interactive:
          $ref: "#/components/schemas/InteractiveMessage"
        template:
          $ref: "#/components/schemas/TemplateMessage"
        reaction:
          $ref: "#/components/schemas/ReactionMessage"
    MarketingMessage:
      type: object
      required:
        - messaging_product
        - type
        - template
      anyOf:
        - required:
            - to
        - required:
            - recipient
      properties:
        messaging_product:
          type: string
          enum:
            - whatsapp
          description: Always "whatsapp"
          example: whatsapp
        recipient_type:
          type: string
          enum:
            - individual
          default: individual
          description: Marketing messages are sent to individual recipients.
        biz_opaque_callback_data:
          type: string
          maxLength: 512
          description: Arbitrary string for tracking (echoed in webhooks)
        to:
          type: string
          description: Recipient phone number. Use `recipient` for BSUID sends.
          example: "15551234567"
        recipient:
          type: string
          description: Recipient BSUID or parent BSUID. If `to` is also present, the phone number in `to` takes precedence.
          example: US.13491208655302741918
        type:
          type: string
          enum:
            - template
          description: Marketing messages must use a WhatsApp template.
          example: template
        template:
          $ref: "#/components/schemas/TemplateMessage"
    MarkReadRequest:
      type: object
      required:
        - messaging_product
        - status
        - message_id
      properties:
        messaging_product:
          type: string
          enum:
            - whatsapp
        status:
          type: string
          enum:
            - read
        message_id:
          type: string
          description: WhatsApp message ID to mark as read
        typing_indicator:
          type: object
          description: Optional typing indicator to display while preparing a reply (dismissed on send or after ~25s)
          properties:
            type:
              type: string
              enum:
                - text
              description: Typing indicator type (currently only "text")
    WhatsappMessageResponse:
      type: object
      required:
        - id
        - timestamp
        - type
      properties:
        id:
          type: string
          description: Message ID
          example: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
        timestamp:
          type: string
          description: Message timestamp (Unix timestamp as string)
          example: "1705328096"
        type:
          $ref: "#/components/schemas/MessageType"
        from:
          type: string
          nullable: true
          description: Sender WhatsApp ID (phone-based identity when available)
          example: "15551234567"
        from_user_id:
          type: string
          nullable: true
          description: Sender business-scoped user ID when available
          example: US.13491208655302741918
        from_parent_user_id:
          type: string
          nullable: true
          description: Sender parent business-scoped user ID when available
          example: US.ENT.506847293015824
        to:
          type: string
          nullable: true
          description: Recipient WhatsApp ID (phone-based identity when available)
          example: "110987654321"
        to_user_id:
          type: string
          nullable: true
          description: Recipient business-scoped user ID when available
          example: US.13491208655302741918
        to_parent_user_id:
          type: string
          nullable: true
          description: Recipient parent business-scoped user ID when available
          example: US.ENT.506847293015824
        username:
          type: string
          nullable: true
          description: WhatsApp username when available
          example: "@testusername"
        context:
          type: object
          description: Reply context
          properties:
            from:
              type: string
              description: Sender of the original message
            id:
              type: string
              description: ID of the message being replied to
            referred_product:
              type: object
              description: Product reference (for catalog messages)
              properties:
                catalog_id:
                  type: string
                product_retailer_id:
                  type: string
        text:
          $ref: "#/components/schemas/TextMessage"
        image:
          $ref: "#/components/schemas/MediaMessage"
        video:
          $ref: "#/components/schemas/MediaMessage"
        audio:
          $ref: "#/components/schemas/AudioMessage"
        document:
          $ref: "#/components/schemas/MediaMessage"
        sticker:
          $ref: "#/components/schemas/StickerMessage"
        location:
          $ref: "#/components/schemas/LocationMessage"
        contacts:
          type: array
          items:
            $ref: "#/components/schemas/ContactCard"
        order:
          $ref: "#/components/schemas/OrderMessage"
        interactive:
          type: object
          description: Interactive message content (for inbound interactive responses).
          properties:
            type:
              type: string
              enum:
                - button_reply
                - list_reply
                - nfm_reply
              description: |-
                Type of interactive response:
                - button_reply: Reply button was tapped
                - list_reply: List item was selected
                - nfm_reply: Native Flow Message (address_message, etc.)
              example: button_reply
            button_reply:
              type: object
              description: Reply button response
              properties:
                id:
                  type: string
                  description: Button ID that was tapped
                  example: button_1
                title:
                  type: string
                  description: Button title that was tapped
                  example: Yes
            list_reply:
              type: object
              description: List selection response
              properties:
                id:
                  type: string
                  description: Row ID that was selected
                  example: row_express
                title:
                  type: string
                  description: Row title that was selected
                  example: Express Shipping
                description:
                  type: string
                  description: Row description
                  example: 1-2 business days
            nfm_reply:
              type: object
              description: Native Flow Message response (e.g., address_message)
              properties:
                name:
                  type: string
                  description: NFM action name
                  example: address_message
                response_json:
                  type: string
                  description: JSON string containing form response data
                  example: '{"values":{"name":"John Doe","in_pin_code":"400063"}}'
                body:
                  type: string
                  description: Human-readable summary of response
                  example: John Doe, +919876543210, 400063, Mumbai
        template:
          type: object
          description: Template message content
        reaction:
          $ref: "#/components/schemas/ReactionMessage"
        kapso:
          type: object
          description: Kapso-specific message extensions
          properties:
            direction:
              type: string
              enum:
                - inbound
                - outbound
              description: Message direction
              example: inbound
            status:
              type: string
              enum:
                - pending
                - sent
                - delivered
                - read
                - failed
              description: Delivery status
              example: delivered
            processing_status:
              type: string
              enum:
                - pending
                - processing
                - completed
                - failed
              description: Processing state
              example: completed
            phone_number:
              type: string
              nullable: true
              description: Associated phone number when phone-based identity is available
              example: "+15559876543"
            has_media:
              type: boolean
              description: Whether message has attached media files
              example: false
            whatsapp_conversation_id:
              type: string
              description: Conversation UUID
              example: 123e4567-e89b-12d3-a456-426614174000
            contact_name:
              type: string
              nullable: true
              description: Contact display name from conversation
              example: John Doe
            content:
              type: string
              nullable: true
              description: Message text content
              example: Hello! I need help with my order
            media_data:
              type: object
              description: Complete media information (when has_media is true)
              properties:
                url:
                  type: string
                  format: uri
                  description: Download URL for the media file
                  example: https://api.kapso.ai/storage/media/abc123.jpg
                filename:
                  type: string
                  description: Original filename
                  example: package.jpg
                content_type:
                  type: string
                  description: MIME type
                  example: image/jpeg
                byte_size:
                  type: integer
                  description: File size in bytes
                  example: 245678
            media_url:
              type: string
              format: uri
              description: Convenience field with just the media URL (when has_media is true)
              example: https://api.kapso.ai/storage/media/abc123.jpg
            message_type_data:
              type: object
              description: Type-specific message data (structure varies by message type)
              additionalProperties: true
            flow_response:
              type: object
              description: Flow response data (for Flow messages)
              additionalProperties: true
            flow_token:
              type: string
              description: Flow session token (for Flow messages)
              example: user_session_abc123
            flow_name:
              type: string
              description: Flow display name (for Flow messages)
              example: Appointment Booking
            order_text:
              type: string
              description: Order text (for order messages)
              example: I'd like to order this item
    SendMessageResponse:
      type: object
      required:
        - messaging_product
        - contacts
        - messages
      properties:
        messaging_product:
          type: string
          enum:
            - whatsapp
          example: whatsapp
        contacts:
          type: array
          items:
            type: object
            properties:
              input:
                type: string
                description: Input phone number, BSUID, or parent BSUID
                example: "15551234567"
              wa_id:
                type: string
                nullable: true
                description: WhatsApp phone number when the message was sent to a phone number
                example: "15551234567"
              user_id:
                type: string
                nullable: true
                description: BSUID or parent BSUID when the message was sent to `recipient`
                example: US.13491208655302741918
        messages:
          type: array
          items:
            type: object
            required:
              - id
            properties:
              id:
                type: string
                description: Message ID
                example: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
              message_status:
                type: string
                enum:
                  - accepted
                  - held_for_quality_assessment
                description: Message pacing status when applicable
    WhatsappConversation:
      type: object
      required:
        - id
        - status
        - last_active_at
        - created_at
        - updated_at
        - whatsapp_config_id
        - phone_number_id
      properties:
        id:
          type: string
          description: Conversation ID (UUID)
          example: 123e4567-e89b-12d3-a456-426614174000
        phone_number:
          type: string
          nullable: true
          description: Contact's phone number (normalized). Can be null for BSUID-only identity.
          example: "15551234567"
        business_scoped_user_id:
          type: string
          nullable: true
          description: WhatsApp business-scoped user ID
          example: US.13491208655302741918
        parent_business_scoped_user_id:
          type: string
          nullable: true
          description: Parent business-scoped user ID when provided by Meta
          example: US.ENT.506847293015824
        username:
          type: string
          nullable: true
          description: WhatsApp username when available
          example: "@testusername"
        status:
          type: string
          enum:
            - active
            - ended
          description: Conversation status
          example: active
        last_active_at:
          type: string
          format: date-time
          description: Last activity timestamp
          example: 2024-01-15T14:30:00.000000Z
        created_at:
          type: string
          format: date-time
          description: Creation timestamp
          example: 2024-01-15T10:00:00.000000Z
        updated_at:
          type: string
          format: date-time
          description: Last update timestamp
          example: 2024-01-15T14:30:00.000000Z
        whatsapp_config_id:
          type: string
          description: WhatsApp configuration ID (UUID)
          example: 456e7890-a12b-34c5-d678-901234567890
        metadata:
          type: object
          description: Custom metadata
          nullable: true
          additionalProperties: true
        phone_number_id:
          type: string
          description: WhatsApp Business Phone Number ID
          example: "110987654321"
        kapso:
          type: object
          description: Kapso-specific conversation metadata
          properties:
            contact_name:
              type: string
              nullable: true
              description: Contact display name
              example: John Doe
            messages_count:
              type: integer
              description: Total message count in conversation
              example: 15
            last_message_id:
              type: string
              nullable: true
              description: WhatsApp message ID of last message
              example: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
            last_message_type:
              type: string
              nullable: true
              description: Type of last message
              example: text
            last_message_timestamp:
              type: string
              format: date-time
              nullable: true
              description: Timestamp of last message (ISO 8601)
              example: 2024-01-15T14:30:00.000000Z
            last_message_text:
              type: string
              nullable: true
              description: Text content of last message (if text message)
              example: Hello! I need help with my order
            last_inbound_at:
              type: string
              format: date-time
              nullable: true
              description: Timestamp of last inbound message (ISO 8601)
              example: 2024-01-15T14:30:00.000000Z
            last_outbound_at:
              type: string
              format: date-time
              nullable: true
              description: Timestamp of last outbound message (ISO 8601)
              example: 2024-01-15T14:25:00.000000Z
    WhatsappCall:
      type: object
      required:
        - id
        - project_id
        - whatsapp_config_id
        - phone_number_id
      properties:
        id:
          type: string
          description: Call ID (UUID)
          example: 123e4567-e89b-12d3-a456-426614174000
        call_id:
          type: string
          description: WhatsApp call ID
          example: call_abc123
        direction:
          type: string
          enum:
            - inbound
            - outbound
          description: Call direction
          example: inbound
        status:
          type: string
          enum:
            - initiated
            - ringing
            - answered
            - completed
            - failed
          description: Call status
          example: completed
        duration_seconds:
          type: integer
          nullable: true
          description: Call duration in seconds
          example: 180
        started_at:
          type: string
          format: date-time
          nullable: true
          description: Call start time
          example: 2024-01-15T12:34:56.123456Z
        ended_at:
          type: string
          format: date-time
          nullable: true
          description: Call end time
          example: 2024-01-15T12:37:56.123456Z
        session_started_at:
          type: string
          format: date-time
          nullable: true
          description: Session start time
          example: 2024-01-15T12:34:58.123456Z
        created_at:
          type: string
          format: date-time
          description: Record creation timestamp
          example: 2024-01-15T12:34:56.000000Z
        updated_at:
          type: string
          format: date-time
          description: Record update timestamp
          example: 2024-01-15T12:37:56.000000Z
        user_wa_id:
          type: string
          nullable: true
          description: User's WhatsApp ID (phone number) when available
          example: "15551234567"
        business_scoped_user_id:
          type: string
          nullable: true
          description: User business-scoped user ID when available
          example: US.13491208655302741918
        parent_business_scoped_user_id:
          type: string
          nullable: true
          description: User parent business-scoped user ID when available
          example: US.ENT.506847293015824
        username:
          type: string
          nullable: true
          description: WhatsApp username when available
          example: "@testusername"
        whatsapp_contact_id:
          type: string
          nullable: true
          description: Associated contact ID (UUID)
          example: 223e4567-e89b-12d3-a456-426614174001
        whatsapp_conversation_id:
          type: string
          nullable: true
          description: Associated conversation ID (UUID)
          example: 323e4567-e89b-12d3-a456-426614174002
        project_id:
          type: string
          description: Project ID (UUID)
          example: 423e4567-e89b-12d3-a456-426614174003
        whatsapp_config_id:
          type: string
          description: WhatsApp configuration ID (UUID)
          example: 523e4567-e89b-12d3-a456-426614174004
        config_display_name:
          type: string
          nullable: true
          description: Configuration display name
          example: Support Line
        config_display_phone_number:
          type: string
          nullable: true
          description: Configuration display phone number
          example: +1 (555) 123-4567
        phone_number_id:
          type: string
          description: WhatsApp Business Phone Number ID
          example: "110987654321"
        whatsapp_contact:
          type: object
          nullable: true
          description: Associated contact (basic view)
          properties:
            id:
              type: string
            wa_id:
              type: string
            profile_name:
              type: string
            display_name:
              type: string
        whatsapp_conversation:
          type: object
          nullable: true
          description: Associated conversation (basic view)
          properties:
            id:
              type: string
            phone_number:
              type: string
            status:
              type: string
            last_active_at:
              type: string
              format: date-time
    FlowSummary:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        status:
          type: string
          enum:
            - DRAFT
            - PUBLISHED
            - DEPRECATED
            - BLOCKED
            - THROTTLED
        categories:
          type: array
          items:
            type: string
        validation_errors:
          type: array
          items:
            $ref: "#/components/schemas/FlowValidationError"
    FlowValidationError:
      type: object
      properties:
        error:
          type: string
        error_type:
          type: string
        message:
          type: string
        line_start:
          type: integer
        line_end:
          type: integer
        column_start:
          type: integer
        column_end:
          type: integer
    FlowCreateRequest:
      type: object
      required:
        - name
        - categories
      properties:
        name:
          type: string
        categories:
          type: array
          items:
            type: string
            enum:
              - SIGN_UP
              - SIGN_IN
              - APPOINTMENT_BOOKING
              - LEAD_GENERATION
              - CONTACT_US
              - CUSTOMER_SUPPORT
              - SURVEY
              - OTHER
        clone_flow_id:
          type: string
        endpoint_uri:
          type: string
          format: uri
        flow_json:
          type: string
        publish:
          type: boolean
    FlowCreateResponse:
      type: object
      properties:
        id:
          type: string
        success:
          type: boolean
        validation_errors:
          type: array
          items:
            $ref: "#/components/schemas/FlowValidationError"
    PhoneNumberSummary:
      type: object
      properties:
        id:
          type: string
          description: Phone number ID
        verified_name:
          type: string
          description: Verified business name associated with the phone number
        display_phone_number:
          type: string
          description: Phone number in international format
        quality_rating:
          type: string
          enum:
            - GREEN
            - YELLOW
            - RED
            - NA
            - UNKNOWN
          description: |
            Quality rating based on message delivery.
            - GREEN: High quality
            - YELLOW: Medium quality
            - RED: Low quality
            - NA: Not yet determined
            - UNKNOWN: Status unknown
        code_verification_status:
          type: string
          description: Verification status of the phone number
        is_official_business_account:
          type: boolean
          description: Whether this is an official business account
        name_status:
          type: string
          description: Status of the business name
        new_name_status:
          type: string
          description: Status of pending name change
        platform_type:
          type: string
          description: Platform type (CLOUD_API, etc.)
        throughput:
          type: object
          description: Messaging throughput limits
        account_mode:
          type: string
          enum:
            - SANDBOX
            - LIVE
          description: Account mode
        certificate:
          type: string
          description: Certificate status
        messaging_limit_tier:
          type: string
          description: Current messaging limit tier
    BusinessVertical:
      type: string
      enum:
        - ALCOHOL
        - APPAREL
        - AUTO
        - BEAUTY
        - EDU
        - ENTERTAIN
        - EVENT_PLAN
        - FINANCE
        - GOVT
        - GROCERY
        - HEALTH
        - HOTEL
        - NONPROFIT
        - ONLINE_GAMBLING
        - OTC_DRUGS
        - OTHER
        - PHYSICAL_GAMBLING
        - PROF_SERVICES
        - RESTAURANT
        - RETAIL
        - TRAVEL
      description: |
        Business category displayed in WhatsApp profile:
        - ALCOHOL: Alcoholic Beverages
        - APPAREL: Clothing and Apparel
        - AUTO: Automotive
        - BEAUTY: Beauty, Spa and Salon
        - EDU: Education
        - ENTERTAIN: Entertainment
        - EVENT_PLAN: Event Planning and Service
        - FINANCE: Finance and Banking
        - GOVT: Public Service
        - GROCERY: Food and Grocery
        - HEALTH: Medical and Health
        - HOTEL: Hotel and Lodging
        - NONPROFIT: Non-profit
        - ONLINE_GAMBLING: Online Gambling & Gaming
        - OTC_DRUGS: Over-the-Counter Drugs
        - OTHER: Other
        - PHYSICAL_GAMBLING: Non-Online Gambling & Gaming
        - PROF_SERVICES: Professional Services
        - RESTAURANT: Restaurant
        - RETAIL: Shopping and Retail
        - TRAVEL: Travel and Transportation
    BusinessProfileUpdate:
      type: object
      required:
        - messaging_product
      properties:
        messaging_product:
          type: string
          enum:
            - whatsapp
          description: Always "whatsapp"
          example: whatsapp
        about:
          type: string
          minLength: 1
          maxLength: 139
          description: |
            Business About text (appears in profile beneath image and contact buttons).
            - Must be 1-139 characters
            - Rendered emojis supported (unicode values must be encoded)
            - Hyperlinks included but won't render as clickable
            - Markdown not supported
          example: Welcome to our store! We're here to help you 24/7.
        address:
          type: string
          maxLength: 256
          description: Business address (max 256 characters)
          example: 123 Main Street, San Francisco, CA 94102
        description:
          type: string
          maxLength: 512
          description: Business description (max 512 characters)
          example: Leading provider of premium products and services since 2010. We pride ourselves on exceptional customer service and quality.
        email:
          type: string
          format: email
          maxLength: 128
          description: Contact email address (max 128 characters)
          example: support@example.com
        profile_picture_handle:
          type: string
          description: Handle from resumable upload API for profile picture
          example: h:resumable-upload-handle-abc123xyz789
        vertical:
          $ref: "#/components/schemas/BusinessVertical"
        websites:
          type: array
          maxItems: 2
          items:
            type: string
            format: uri
            maxLength: 256
          description: URLs associated with business (max 2, 256 chars each, must include http:// or https://)
          example:
            - https://www.example.com
            - https://www.instagram.com/example
    BusinessProfileUpdateResponse:
      type: object
      required:
        - success
      properties:
        success:
          type: boolean
          description: Whether the update succeeded
          example: true
paths:
  /{phone_number_id}/messages:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Messages
      summary: List messages
      description: |
        Retrieve a paginated list of WhatsApp messages for a phone number.

        Supports filtering by conversation, direction, status, and time range.
        Uses cursor-based pagination for efficient scrolling through large result sets.
      operationId: listMessages
      parameters:
        - name: conversation_id
          in: query
          description: Filter by conversation ID
          schema:
            type: string
          example: 123e4567-e89b-12d3-a456-426614174000
        - name: direction
          in: query
          description: Filter by message direction
          schema:
            type: string
            enum:
              - inbound
              - outbound
          example: inbound
        - name: status
          in: query
          description: Filter by message status
          schema:
            type: string
            enum:
              - pending
              - sent
              - delivered
              - read
              - failed
          example: delivered
        - name: since
          in: query
          description: Filter messages created on or after this time (ISO 8601)
          schema:
            type: string
            format: date-time
          example: 2024-01-15T00:00:00Z
        - name: until
          in: query
          description: Filter messages created on or before this time (ISO 8601)
          schema:
            type: string
            format: date-time
          example: 2024-01-15T23:59:59Z
        - name: limit
          in: query
          description: Maximum number of results per page (default 20, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
          example: 20
        - name: before
          in: query
          description: Cursor for previous page (Base64 encoded)
          schema:
            type: string
          example: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
        - name: after
          in: query
          description: Cursor for next page (Base64 encoded)
          schema:
            type: string
          example: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNFQwOToyMTozMi43ODkwMTJaIiwiMTIzMjAiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
        - name: fields
          in: query
          description: |
            Filter response fields. Use `kapso()` to include Kapso-specific extensions.

            Example: `fields=kapso(direction,status,processing_status)`
          schema:
            type: string
          example: kapso()
      responses:
        "200":
          description: Successfully retrieved messages
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WhatsappMessageResponse"
                  paging:
                    $ref: "#/components/schemas/Paging"
              examples:
                inbound_text:
                  summary: Inbound text message
                  description: Basic text message from customer with core kapso fields
                  value:
                    data:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                        timestamp: "1705328096"
                        type: text
                        from: "15551234567"
                        text:
                          body: Hello! I need help with my order
                        kapso:
                          direction: inbound
                          status: delivered
                          processing_status: completed
                          phone_number: "+15551234567"
                          has_media: false
                          whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                          contact_name: John Doe
                          content: Hello! I need help with my order
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
                outbound_image:
                  summary: Outbound image with caption
                  description: Image message with media fields and type-specific data
                  value:
                    data:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFCAA==
                        timestamp: "1705328150"
                        type: image
                        to: "15551234567"
                        image:
                          id: abc123def456
                          caption: Your order has been shipped!
                        kapso:
                          direction: outbound
                          status: sent
                          processing_status: completed
                          phone_number: "+15551234567"
                          has_media: true
                          whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                          contact_name: John Doe
                          media_data:
                            url: https://api.kapso.ai/storage/media/abc123.jpg
                            filename: package.jpg
                            content_type: image/jpeg
                            byte_size: 245678
                          media_url: https://api.kapso.ai/storage/media/abc123.jpg
                          message_type_data:
                            caption: Your order has been shipped!
                            has_media: true
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
                template_message:
                  summary: Template message
                  description: Outbound template with template-specific kapso data
                  value:
                    data:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFDAA==
                        timestamp: "1705328200"
                        type: template
                        to: "15551234567"
                        template:
                          name: order_confirmation
                          language:
                            code: en_US
                          components:
                            - type: body
                              parameters:
                                - type: text
                                  text: John
                                - type: text
                                  text: ORD-12345
                        kapso:
                          direction: outbound
                          status: delivered
                          processing_status: completed
                          phone_number: "+15551234567"
                          has_media: false
                          whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                          contact_name: John Doe
                          message_type_data:
                            name: order_confirmation
                            language:
                              code: en_US
                            params:
                              - John
                              - ORD-12345
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
                interactive_message:
                  summary: Interactive button message
                  description: Interactive message with type-specific data
                  value:
                    data:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFEAA==
                        timestamp: "1705328250"
                        type: interactive
                        to: "15551234567"
                        interactive:
                          type: button
                          body:
                            text: Would you like to proceed with your order?
                        kapso:
                          direction: outbound
                          status: sent
                          processing_status: completed
                          phone_number: "+15551234567"
                          has_media: false
                          whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                          contact_name: John Doe
                          message_type_data:
                            type: button
                            body_text: Would you like to proceed with your order?
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
                location_message:
                  summary: Location share
                  description: Inbound location message with coordinates and details
                  value:
                    data:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFFAA==
                        timestamp: "1705328300"
                        type: location
                        from: "15551234567"
                        location:
                          latitude: 37.7749
                          longitude: -122.4194
                          name: Warehouse Location
                          address: 123 Main St, San Francisco, CA
                        kapso:
                          direction: inbound
                          status: delivered
                          processing_status: completed
                          phone_number: "+15551234567"
                          has_media: false
                          whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                          contact_name: John Doe
                          message_type_data:
                            latitude: 37.7749
                            longitude: -122.4194
                            name: Warehouse Location
                            address: 123 Main St, San Francisco, CA
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMjozNDo1Ni4xMjM0NTZaIiwiMTIzNDUiXSwiY29sdW1ucyI6WyJjcmVhdGVkX2F0IiwiaWQiXX0=
        "400":
          description: Bad request (invalid parameters)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized (invalid or missing API key)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Phone number not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Messages
      summary: Send a message
      description: |
        Send a WhatsApp message to a recipient.

        Use `to` for phone numbers. Use `recipient` for a BSUID or parent BSUID.
        If both are present, the phone number in `to` takes precedence.

        Supports all WhatsApp message types:
        - **text**: Plain text messages with optional URL preview
        - **image**: Images with optional caption
        - **video**: Videos with optional caption
        - **audio**: Audio files
        - **document**: Documents with optional caption and filename
        - **sticker**: Stickers
        - **location**: Location sharing
        - **contacts**: Contact cards
        - **interactive**: Interactive messages (buttons, lists, flows)
        - **template**: Message templates
        - **reaction**: Emoji reactions to messages
      operationId: sendMessage
      requestBody:
        required: true
        content:
          application/json:
            schema:
              oneOf:
                - $ref: "#/components/schemas/WhatsappMessage"
                - $ref: "#/components/schemas/MarkReadRequest"
            examples:
              text_message:
                summary: Send text message
                value:
                  messaging_product: whatsapp
                  recipient_type: individual
                  to: "15551234567"
                  type: text
                  text:
                    body: "Hello! Your order #12345 has been shipped."
              text_message_to_bsuid:
                summary: Send text message to BSUID
                description: Non-template messages require an open 24-hour customer service window.
                value:
                  messaging_product: whatsapp
                  recipient_type: individual
                  recipient: US.13491208655302741918
                  type: text
                  text:
                    body: "Hello! Your order #12345 has been shipped."
              template_to_bsuid:
                summary: Send template to BSUID
                value:
                  messaging_product: whatsapp
                  recipient_type: individual
                  recipient: US.13491208655302741918
                  type: template
                  template:
                    name: order_update
                    language:
                      code: en_US
              image_message:
                summary: Send image with caption
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: image
                  image:
                    link: https://example.com/product.jpg
                    caption: Check out our new product!
              voice_message:
                summary: Send voice message (voice note)
                description: |-
                  Voice messages must be .ogg files encoded with OPUS codec.
                  Includes automatic download, profile picture, voice icon, and optional transcription.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: audio
                  audio:
                    id: "1013859600285441"
                    voice: true
              basic_audio_message:
                summary: Send basic audio message
                description: |-
                  Basic audio messages display a download icon and music icon.
                  Supports AAC, AMR, MP3, MP4, and OGG formats (max 16MB).
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: audio
                  audio:
                    link: https://example.com/ringtone.mp3
              template_named_params:
                summary: Template with named parameters
                description: |
                  Named parameters allow flexible ordering and clearer intent.
                  Use `parameter_name` field to specify which variable to fill.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: order_confirmation
                    language:
                      code: en_US
                    components:
                      - type: body
                        parameters:
                          - type: text
                            parameter_name: first_name
                            text: Jessica
                          - type: text
                            parameter_name: order_number
                            text: SKBUP2-4CPIG9
              template_positional_params:
                summary: Template with positional parameters
                description: |
                  Positional parameters must appear in order ({{1}}, {{2}}, etc.).
                  Order matters - first param fills {{1}}, second fills {{2}}.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: order_confirmation
                    language:
                      code: en_US
                    components:
                      - type: body
                        parameters:
                          - type: text
                            text: Jessica
                          - type: text
                            text: SKBUP2-4CPIG9
              template_with_media_header:
                summary: Template with image header and named params
                description: |
                  Headers can include media (image/video/document).
                  Use media ID from upload endpoint or public URL.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: seasonal_promotion
                    language:
                      code: en_US
                    components:
                      - type: header
                        parameters:
                          - type: image
                            image:
                              link: https://example.com/summer-sale.jpg
                      - type: body
                        parameters:
                          - type: text
                            parameter_name: sale_name
                            text: Summer Sale
                          - type: text
                            parameter_name: discount_code
                            text: SUMMER25
                          - type: text
                            parameter_name: discount_amount
                            text: 25%
              template_with_header_footer:
                summary: Template with text header and footer
                description: |
                  Text headers support 1 parameter (named or positional).
                  Footers are static text defined in template.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: seasonal_promotion
                    language:
                      code: en_US
                    components:
                      - type: header
                        parameters:
                          - type: text
                            parameter_name: sale_name
                            text: Black Friday Sale
                      - type: body
                        parameters:
                          - type: text
                            parameter_name: end_date
                            text: November 30th
                          - type: text
                            parameter_name: discount_code
                            text: BF2024
              template_with_url_button:
                summary: Template with URL button variable
                description: |
                  URL buttons can have 1 variable at the end.
                  Use button component with sub_type URL and index.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: limited_time_offer
                    language:
                      code: en_US
                    components:
                      - type: body
                        parameters:
                          - type: text
                            parameter_name: customer_name
                            text: Mark
                          - type: text
                            parameter_name: package_name
                            text: Premium Package
                      - type: button
                        sub_type: url
                        index: "0"
                        parameters:
                          - type: text
                            text: summer2024
              template_with_quick_reply:
                summary: Template with quick reply buttons
                description: |
                  Quick reply buttons use payload parameter.
                  Index determines button order (0-based).
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: customer_feedback
                    language:
                      code: en_US
                    components:
                      - type: body
                        parameters:
                          - type: text
                            parameter_name: customer_name
                            text: Sarah
                      - type: button
                        sub_type: quick_reply
                        index: "0"
                        parameters:
                          - type: payload
                            payload: yes_helpful
                      - type: button
                        sub_type: quick_reply
                        index: "1"
                        parameters:
                          - type: payload
                            payload: no_not_helpful
              template_with_flow:
                summary: Template with flow button
                description: |
                  Flow buttons trigger WhatsApp Flows.
                  Pass flow_token and flow_action_data as parameters.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: template
                  template:
                    name: appointment_booking
                    language:
                      code: en_US
                    components:
                      - type: body
                        parameters:
                          - type: text
                            parameter_name: customer_name
                            text: Michael
                      - type: button
                        sub_type: flow
                        index: "0"
                        parameters:
                          - type: action
                            action:
                              flow_token: user_session_abc123
                              flow_action_data:
                                customer_id: cust_12345
                                preferred_date: 2024-02-15
              interactive_button:
                summary: Send interactive button message
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: button
                    body:
                      text: Would you like to proceed with your order?
                    action:
                      buttons:
                        - type: reply
                          reply:
                            id: btn_yes
                            title: Yes
                        - type: reply
                          reply:
                            id: btn_no
                            title: No
              interactive_cta_url:
                summary: Interactive CTA URL button
                description: |-
                  Send a call-to-action button that opens a URL.
                  Useful for obscuring long tracking URLs.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: cta_url
                    header:
                      type: text
                      text: New workshop dates announced!
                    body:
                      text: Tap the button below to see available dates.
                    footer:
                      text: Dates subject to change
                    action:
                      name: cta_url
                      parameters:
                        display_text: See Dates
                        url: https://example.com/workshops?utm_source=whatsapp
              interactive_order_details_pix:
                summary: Interactive order details with dynamic Pix
                description: |-
                  Send an order for the user to review and pay with Pix.
                  Requires a WhatsApp Business Account enabled for the Meta Brazil Payments API.
                value:
                  messaging_product: whatsapp
                  to: "5511999999999"
                  type: interactive
                  interactive:
                    type: order_details
                    body:
                      text: Order details
                    action:
                      name: review_and_pay
                      parameters:
                        reference_id: pix-order-123
                        type: digital-goods
                        payment_type: br
                        payment_settings:
                          - type: pix_dynamic_code
                            pix_dynamic_code:
                              code: 00020101021226820014br.gov.bcb.pix
                              merchant_name: Kapso Merchant
                              key: "12345678000199"
                              key_type: CNPJ
                        currency: BRL
                        total_amount:
                          value: 1000
                          offset: 100
                        order:
                          status: pending
                          tax:
                            value: 0
                            offset: 100
                          items:
                            - retailer_id: item-1
                              name: Subscription
                              amount:
                                value: 1000
                                offset: 100
                              quantity: 1
                          subtotal:
                            value: 1000
                            offset: 100
              interactive_order_status:
                summary: Interactive order status update
                description: |-
                  Update a previously sent order using the same reference_id.
                value:
                  messaging_product: whatsapp
                  to: "5511999999999"
                  type: interactive
                  interactive:
                    type: order_status
                    body:
                      text: Payment confirmed
                    action:
                      name: review_order
                      parameters:
                        reference_id: pix-order-123
                        order:
                          status: processing
                        payment:
                          status: captured
              interactive_carousel_url:
                summary: Interactive carousel with URL buttons
                description: |-
                  Send a free-form media carousel with 2-10 cards. Each card includes
                  an image or video header and a CTA URL button.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: carousel
                    body:
                      text: Choose a trip option
                    action:
                      cards:
                        - card_index: 0
                          type: cta_url
                          header:
                            type: image
                            image:
                              link: https://example.com/flight-a.jpg
                          body:
                            text: Morning flight
                          action:
                            name: cta_url
                            parameters:
                              display_text: View
                              url: https://example.com/flights/a
                        - card_index: 1
                          type: cta_url
                          header:
                            type: image
                            image:
                              link: https://example.com/flight-b.jpg
                          body:
                            text: Evening flight
                          action:
                            name: cta_url
                            parameters:
                              display_text: View
                              url: https://example.com/flights/b
              interactive_carousel_quick_reply:
                summary: Interactive carousel with quick replies
                description: |-
                  Send a free-form media carousel where every card has the same
                  quick-reply button structure.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: carousel
                    body:
                      text: Pick a product
                    action:
                      cards:
                        - card_index: 0
                          type: cta_url
                          header:
                            type: image
                            image:
                              link: https://example.com/product-a.jpg
                          action:
                            buttons:
                              - type: quick_reply
                                quick_reply:
                                  id: product_a_yes
                                  title: Select
                        - card_index: 1
                          type: cta_url
                          header:
                            type: image
                            image:
                              link: https://example.com/product-b.jpg
                          action:
                            buttons:
                              - type: quick_reply
                                quick_reply:
                                  id: product_b_yes
                                  title: Select
              interactive_list:
                summary: Interactive list message
                description: |-
                  Send a list picker with sections and rows.
                  Maximum 10 sections, 10 total rows across all sections.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: list
                    header:
                      type: text
                      text: Choose Shipping
                    body:
                      text: Which shipping option do you prefer?
                    footer:
                      text: Shipping estimates may vary
                    action:
                      button: View Options
                      sections:
                        - title: Fast Shipping
                          rows:
                            - id: express
                              title: Express
                              description: 1-2 days
                            - id: priority
                              title: Priority
                              description: 2-3 days
                        - title: Standard Shipping
                          rows:
                            - id: standard
                              title: Standard
                              description: 5-7 days
              interactive_location_request:
                summary: Request user's location
                description: |-
                  Request the user to share their current location.
                  Displays a "Send Location" button.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: location_request_message
                    body:
                      text: Please share your location so we can provide accurate delivery estimates.
                    action:
                      name: send_location
              interactive_request_contact_info:
                summary: Request user's phone number
                description: Ask a user to share their WhatsApp phone number in-thread.
                value:
                  messaging_product: whatsapp
                  recipient_type: individual
                  recipient: US.13491208655302741918
                  type: interactive
                  interactive:
                    type: request_contact_info
                    body:
                      text: Please share your phone number so we can finish your request.
                    action:
                      name: request_contact_info
              interactive_address_message:
                summary: Request address (India only)
                description: |-
                  Request a structured address from user.

                  IMPORTANT: Address messages are only available for businesses based in India
                  and their India customers. The `country` parameter must be "IN".

                  Can include pre-filled values and saved addresses.
                value:
                  messaging_product: whatsapp
                  to: "919876543210"
                  type: interactive
                  interactive:
                    type: address_message
                    body:
                      text: Please provide your delivery address.
                    action:
                      name: address_message
                      parameters:
                        country: IN
                        values:
                          name: John Doe
                          phone_number: "+919876543210"
                        saved_addresses:
                          - id: home
                            value:
                              name: John Doe
                              phone_number: "+919876543210"
                              in_pin_code: "400063"
                              floor_number: "8"
                              building_name: Acme Tower
                              address: MG Road
                              landmark_area: Near Metro
                              city: Mumbai
              interactive_address_validation_error:
                summary: Address validation error (India)
                description: |-
                  Re-send address request with validation errors.
                  User sees their previous input with error messages.
                value:
                  messaging_product: whatsapp
                  to: "919876543210"
                  type: interactive
                  interactive:
                    type: address_message
                    body:
                      text: Please correct the errors in your address.
                    action:
                      name: address_message
                      parameters:
                        country: IN
                        values:
                          name: John Doe
                          phone_number: "+919876543210"
                          in_pin_code: "999999"
                          address: Some Street
                          city: Mumbai
                        validation_errors:
                          in_pin_code: Invalid PIN code. Please check and try again.
              interactive_flow:
                summary: WhatsApp Flow message
                description: |-
                  Send a WhatsApp Flow to collect structured data.
                  Requires pre-created Flow in WhatsApp Manager.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: flow
                    header:
                      type: text
                      text: Appointment Booking
                    body:
                      text: Book your appointment using our interactive form
                    footer:
                      text: Available slots shown in real-time
                    action:
                      name: flow
                      parameters:
                        flow_message_version: "3"
                        flow_id: "123456789"
                        flow_cta: Book Now
                        mode: published
                        flow_token: AQAAAAACS5FpgQ_cAAAAAD0QI3s.
                        flow_action: navigate
                        flow_action_payload:
                          screen: BOOKING_SCREEN
                          data:
                            service_type: consultation
                            preferred_date: 2024-02-15
              call_permission_request:
                summary: Call permission request
                value:
                  messaging_product: whatsapp
                  recipient_type: individual
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: call_permission_request
                    action:
                      name: call_permission_request
                    body:
                      text: We would like to call you to help with your order.
              interactive_product:
                summary: Single product message
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: product
                    body:
                      text: Optional body text
                    action:
                      catalog_id: CATALOG_ID
                      product_retailer_id: SKU_1234
              interactive_product_list:
                summary: Multi-product message
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: product_list
                    header:
                      type: text
                      text: Our bestsellers
                    body:
                      text: Choose a product
                    footer:
                      text: While supplies last
                    action:
                      catalog_id: CATALOG_ID
                      sections:
                        - title: Popular
                          product_items:
                            - product_retailer_id: SKU_1234
                            - product_retailer_id: SKU_2345
              interactive_catalog_message:
                summary: Browse catalog
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: interactive
                  interactive:
                    type: catalog_message
                    body:
                      text: Browse our catalog on WhatsApp.
                    action:
                      name: catalog_message
                      parameters:
                        thumbnail_product_retailer_id: SKU_THUMBNAIL
              reply_message:
                summary: Reply to a message
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: text
                  context:
                    message_id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                  text:
                    body: Thank you for your message! I'll get back to you soon.
              document_message:
                summary: Send document with caption
                description: |-
                  Send a PDF, Word, Excel, or other document file.
                  Supports various document formats up to 100MB.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: document
                  document:
                    id: "1376223850470843"
                    filename: invoice_2024.pdf
                    caption: Your invoice for January 2024
              video_message:
                summary: Send video with caption
                description: |-
                  Send a video file (3GP or MP4).
                  H.264 video codec and AAC audio codec required.
                  Maximum 16MB.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: video
                  video:
                    id: "1166846181421424"
                    caption: Product demonstration video
              sticker_message:
                summary: Send sticker
                description: |-
                  Send animated or static sticker (WEBP format).
                  Static: 100KB max, Animated: 500KB max.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: sticker
                  sticker:
                    id: "798882015472548"
              location_message:
                summary: Send location
                description: Send a location with coordinates, name, and address.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: location
                  location:
                    latitude: "37.7749"
                    longitude: "-122.4194"
                    name: San Francisco Office
                    address: 123 Market St, San Francisco, CA 94103
              reaction_message:
                summary: React to a message
                description: |-
                  Send an emoji reaction to a previous message.

                  LIMITATION: Reaction messages only trigger a 'sent' status webhook.
                  Delivered and read webhooks are NOT triggered for reaction messages.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: reaction
                  reaction:
                    message_id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                    emoji: 👍
              contacts_message:
                summary: Send contact card
                description: |-
                  Send rich contact information with addresses, phones, emails, and more.

                  WARNING: While the API supports up to 257 contacts per message, sending many contacts
                  may result in negative user feedback. Consider sending fewer contacts for better UX.
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  type: contacts
                  contacts:
                    - addresses:
                        - street: 1 Lucky Shrub Way
                          city: Menlo Park
                          state: CA
                          zip: "94025"
                          country: United States
                          country_code: US
                          type: Office
                      birthday: 1999-01-23
                      emails:
                        - email: bjohnson@luckyshrub.com
                          type: Work
                      name:
                        formatted_name: Barbara J. Johnson
                        first_name: Barbara
                        last_name: Johnson
                        middle_name: Joana
                        suffix: Esq.
                        prefix: Dr.
                      org:
                        company: Lucky Shrub
                        department: Legal
                        title: Lead Counsel
                      phones:
                        - phone: "+16505559999"
                          type: Landline
                        - phone: "+19175559999"
                          type: Mobile
                          wa_id: "19175559999"
                      urls:
                        - url: https://www.luckyshrub.com
                          type: Company
              mark_read_with_typing:
                summary: Mark message as read and show typing
                value:
                  messaging_product: whatsapp
                  status: read
                  message_id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                  typing_indicator:
                    type: text
      responses:
        "200":
          description: Message sent successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SendMessageResponse"
              examples:
                success:
                  summary: Successful send
                  value:
                    messaging_product: whatsapp
                    contacts:
                      - input: "15551234567"
                        wa_id: "15551234567"
                    messages:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                bsuid_success:
                  summary: Successful BSUID send
                  value:
                    messaging_product: whatsapp
                    contacts:
                      - input: US.13491208655302741918
                        user_id: US.13491208655302741918
                    messages:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdCMDEyOTcxQzFFQkFBAA==
        "400":
          description: Bad request (invalid message format or parameters)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalid_phone:
                  summary: Invalid phone number
                  value:
                    error:
                      message: Invalid phone number format
                      type: OAuthException
                      code: 400
                      error_subcode: 1001
        "401":
          description: Unauthorized (invalid or missing API key)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "402":
          description: Project has insufficient Kapso credits for Meta messaging fees
          content:
            application/json:
              schema:
                type: object
                required:
                  - error
                  - code
                  - billing_url
                properties:
                  error:
                    type: string
                    description: Human-readable error message
                  code:
                    type: string
                    enum:
                      - insufficient_credits
                  billing_url:
                    type: string
                    format: uri
                    description: Kapso billing page where credits can be added
              example:
                error: Your Kapso balance doesn't cover Meta's fee for this message.
                code: insufficient_credits
                billing_url: https://app.kapso.ai/projects/00000000-0000-0000-0000-000000000000/billing
        "404":
          description: Phone number not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "409":
          description: Conflict - Another message is already being sent to this recipient
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                message_in_flight:
                  summary: Message already in-flight
                  description: A message is currently being sent to this recipient. Wait and retry.
                  value:
                    error: Another message is already in-flight for this conversation. Please retry shortly.
        "422":
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/Error"
                  - $ref: "#/components/schemas/MarketingPreferenceStoppedError"
              examples:
                window_expired:
                  summary: 24-hour window expired
                  description: Cannot send non-template messages outside the 24-hour window
                  value:
                    error:
                      message: Cannot send non-template messages outside the 24-hour window.
                      type: MessageError
                      code: 131047
                      error_subcode: 131047
                      fbtrace_id: AXk7s_8dR4eVHp9Kq2MmNlO
                address_not_supported:
                  summary: Address message not supported
                  description: |-
                    Client does not support address_message feature.
                    Message is silently dropped.
                  value:
                    error:
                      message: Receiver Incapable
                      type: MessageError
                      code: 1026
                      error_subcode: 1026
                      href: https://developers.facebook.com/docs/whatsapp/api/errors/
                marketing_preference_stopped:
                  summary: Contact stopped marketing messages
                  description: |-
                    The contact asked WhatsApp to stop marketing messages from
                    this number. Marketing template sends are refused before
                    reaching Meta and are not charged. Do not retry — use a
                    utility or authentication template, or another number.
                  value:
                    error: Contact stopped marketing messages on this WhatsApp number
                    code: marketing_preference_stopped
  /{phone_number_id}/marketing_messages:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    post:
      tags:
        - Messages
      summary: Send a marketing message
      description: |
        Send a WhatsApp marketing template message.

        Use `to` for phone numbers. Use `recipient` for a BSUID or parent BSUID.
        If both are present, the phone number in `to` takes precedence.
      operationId: sendMarketingMessage
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/MarketingMessage"
            examples:
              marketing_template_to_bsuid:
                summary: Send marketing template to BSUID
                value:
                  messaging_product: whatsapp
                  recipient_type: individual
                  recipient: US.13491208655302741918
                  type: template
                  template:
                    name: promo_template
                    language:
                      code: en_US
      responses:
        "200":
          description: Message accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SendMessageResponse"
              examples:
                bsuid_success:
                  summary: Successful BSUID send
                  value:
                    messaging_product: whatsapp
                    contacts:
                      - input: US.13491208655302741918
                        user_id: US.13491208655302741918
                    messages:
                      - id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdCMDEyOTcxQzFFQkFBAA==
                        message_status: accepted
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/Error"
                  - $ref: "#/components/schemas/MarketingPreferenceStoppedError"
              examples:
                marketing_preference_stopped:
                  summary: Contact stopped marketing messages
                  description: |-
                    The contact asked WhatsApp to stop marketing messages from
                    this number. The send is refused before reaching Meta and
                    is not charged. Do not retry — use a utility or
                    authentication template, or another number.
                  value:
                    error: Contact stopped marketing messages on this WhatsApp number
                    code: marketing_preference_stopped
  /{phone_number_id}/username:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Usernames
      summary: Get current username
      operationId: getUsername
      responses:
        "200":
          description: Current username state
          content:
            application/json:
              schema:
                type: object
                properties:
                  username:
                    type: string
                    description: Current business username. Omitted when none exists.
                    example: kapso_support
                  status:
                    type: string
                    enum:
                      - approved
                      - reserved
                    example: reserved
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Usernames
      summary: Claim or change username
      operationId: setUsername
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - username
              properties:
                username:
                  type: string
                  description: Desired business username
                  example: kapso_support
                transfer_action:
                  type: string
                  enum:
                    - none
                    - force_transfer
                  default: none
                  description: Use `force_transfer` to move a username from another phone number in the same business portfolio.
            examples:
              claim_username:
                summary: Claim username
                value:
                  username: kapso_support
                  transfer_action: none
      responses:
        "200":
          description: Username request accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - approved
                      - reserved
                    example: reserved
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - Usernames
      summary: Delete username
      operationId: deleteUsername
      responses:
        "200":
          description: Username deleted
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/username_suggestions:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Usernames
      summary: Get reserved username suggestions
      operationId: getUsernameSuggestions
      responses:
        "200":
          description: Reserved username suggestions
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        username_suggestions:
                          type: array
                          items:
                            type: string
                          example:
                            - kapso_support
                            - kapso_ai
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/messages/{message_id}:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
      - name: message_id
        in: path
        required: true
        description: WhatsApp message ID
        schema:
          type: string
        example: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
    get:
      tags:
        - Messages
      summary: Get message by ID
      description: |
        Retrieve a single WhatsApp message by its message ID.

        Returns the message with all its fields, including Kapso extensions like status, direction, and processing state.
      operationId: getMessage
      parameters:
        - name: fields
          in: query
          description: |
            Filter response fields. Use `kapso()` to include Kapso-specific extensions.

            Example: `fields=kapso(direction,status,processing_status)`
          schema:
            type: string
          example: kapso()
      responses:
        "200":
          description: Successfully retrieved message
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WhatsappMessageResponse"
              examples:
                inbound_text:
                  summary: Inbound text message
                  value:
                    id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                    timestamp: "1705328096"
                    type: text
                    from: "15551234567"
                    text:
                      body: Hello! I need help with my order
                    kapso:
                      direction: inbound
                      status: delivered
                      processing_status: completed
                      phone_number: "+15551234567"
                      has_media: false
                      whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                      contact_name: John Doe
                      content: Hello! I need help with my order
                outbound_image:
                  summary: Outbound image with caption
                  value:
                    id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFCAA==
                    timestamp: "1705328150"
                    type: image
                    to: "15551234567"
                    image:
                      id: abc123def456
                      caption: Your order has been shipped!
                    kapso:
                      direction: outbound
                      status: sent
                      processing_status: completed
                      phone_number: "+15551234567"
                      has_media: true
                      whatsapp_conversation_id: 123e4567-e89b-12d3-a456-426614174000
                      contact_name: John Doe
                      media_data:
                        url: https://api.kapso.ai/storage/media/abc123.jpg
                        filename: package.jpg
                        content_type: image/jpeg
                        byte_size: 245678
                      media_url: https://api.kapso.ai/storage/media/abc123.jpg
                      message_type_data:
                        caption: Your order has been shipped!
                        has_media: true
        "401":
          description: Unauthorized (invalid or missing API key)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Message not found or doesn't belong to this phone number
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error:
                  message: Message not found
                  type: MessageError
                  code: 404
  /{phone_number_id}/conversations:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Conversations
      summary: List conversations
      description: |
        Retrieve a paginated list of WhatsApp conversations for a phone number.

        Conversations are ordered by last activity (most recent first).
        Supports filtering by status, activity time range, and phone number.

        ## Kapso Extensions

        The response includes Kapso-specific conversation metadata:
        - Message counts (total and unread)
        - Associated contact information
        - Conversation status and timestamps
      operationId: listConversations
      parameters:
        - name: status
          in: query
          description: Filter by conversation status
          schema:
            type: string
            enum:
              - active
              - ended
          example: active
        - name: assigned_user_id
          in: query
          description: Filter by active assignee user ID (must be a project member)
          schema:
            type: string
            format: uuid
          example: 123e4567-e89b-12d3-a456-426614174000
        - name: unassigned
          in: query
          description: Filter conversations with no active assignment. Cannot be combined with `assigned_user_id`.
          schema:
            type: boolean
          example: true
        - name: last_active_since
          in: query
          description: Filter conversations active on or after this time (ISO 8601)
          schema:
            type: string
            format: date-time
          example: 2024-01-15T00:00:00Z
        - name: last_active_until
          in: query
          description: Filter conversations active on or before this time (ISO 8601)
          schema:
            type: string
            format: date-time
          example: 2024-01-15T23:59:59Z
        - name: phone_number
          in: query
          description: Filter by contact phone number
          schema:
            type: string
          example: "+15551234567"
        - name: limit
          in: query
          description: Maximum number of results per page (default 20, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
          example: 20
        - name: before
          in: query
          description: Cursor for previous page (Base64 encoded)
          schema:
            type: string
        - name: after
          in: query
          description: Cursor for next page (Base64 encoded)
          schema:
            type: string
        - name: fields
          in: query
          description: Filter response fields. Use `kapso()` to include Kapso-specific extensions.
          schema:
            type: string
          example: kapso()
      responses:
        "200":
          description: Successfully retrieved conversations
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WhatsappConversation"
                  paging:
                    $ref: "#/components/schemas/Paging"
              examples:
                success:
                  summary: List of conversations
                  value:
                    data:
                      - id: 123e4567-e89b-12d3-a456-426614174000
                        phone_number: "15551234567"
                        status: active
                        last_active_at: 2024-01-15T14:30:00.000000Z
                        created_at: 2024-01-15T10:00:00.000000Z
                        updated_at: 2024-01-15T14:30:00.000000Z
                        whatsapp_config_id: 456e7890-a12b-34c5-d678-901234567890
                        metadata:
                          tags:
                            - vip
                            - priority
                        phone_number_id: "110987654321"
                        kapso:
                          contact_name: John Doe
                          messages_count: 15
                          last_message_id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                          last_message_type: text
                          last_message_timestamp: 2024-01-15T14:30:00.000000Z
                          last_message_text: Hello! I need help with my order
                          last_inbound_at: 2024-01-15T14:30:00.000000Z
                          last_outbound_at: 2024-01-15T14:25:00.000000Z
                      - id: 223e4567-e89b-12d3-a456-426614174001
                        phone_number: "15559876543"
                        status: ended
                        last_active_at: 2024-01-14T12:00:00.000000Z
                        created_at: 2024-01-14T08:00:00.000000Z
                        updated_at: 2024-01-14T12:00:00.000000Z
                        whatsapp_config_id: 456e7890-a12b-34c5-d678-901234567890
                        metadata: null
                        phone_number_id: "110987654321"
                        kapso:
                          contact_name: Jane Smith
                          messages_count: 8
                          last_message_id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAB==
                          last_message_type: text
                          last_message_timestamp: 2024-01-14T12:00:00.000000Z
                          last_message_text: Thank you for your help!
                          last_inbound_at: 2024-01-14T12:00:00.000000Z
                          last_outbound_at: 2024-01-14T11:58:00.000000Z
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNFQxMjowMDowMC4wMDAwMDBaIiwiMjIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDAxIl0sImNvbHVtbnMiOlsibGFzdF9hY3RpdmVfYXQiLCJpZCJdfQ==
        "400":
          description: Bad request (invalid parameters)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized (invalid or missing API key)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Phone number not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "422":
          description: Validation error (conflicting filters or invalid assignee)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/conversations/{conversation_id}:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
      - name: conversation_id
        in: path
        required: true
        description: Conversation ID
        schema:
          type: string
        example: 123e4567-e89b-12d3-a456-426614174000
    get:
      tags:
        - Conversations
      summary: Get conversation details
      description: |
        Retrieve detailed information about a specific conversation.

        ## Kapso Extensions

        The response includes:
        - Full contact information
        - Message statistics
        - Conversation metadata
      operationId: getConversation
      parameters:
        - name: fields
          in: query
          description: Filter response fields. Use `kapso()` to include Kapso-specific extensions.
          schema:
            type: string
          example: kapso()
      responses:
        "200":
          description: Successfully retrieved conversation
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WhatsappConversation"
              examples:
                success:
                  summary: Conversation details
                  value:
                    id: 123e4567-e89b-12d3-a456-426614174000
                    phone_number: "15551234567"
                    status: active
                    last_active_at: 2024-01-15T14:30:00.000000Z
                    created_at: 2024-01-15T10:00:00.000000Z
                    updated_at: 2024-01-15T14:30:00.000000Z
                    whatsapp_config_id: 456e7890-a12b-34c5-d678-901234567890
                    metadata:
                      tags:
                        - vip
                        - priority
                      customer_tier: premium
                    phone_number_id: "110987654321"
                    kapso:
                      contact_name: John Doe
                      messages_count: 15
                      last_message_id: wamid.HBgNMTU1NTE0OTU5Nzg1FQIAERgSMDhGRjdBMDEyOTcxQzFFQkFBAA==
                      last_message_type: text
                      last_message_timestamp: 2024-01-15T14:30:00.000000Z
                      last_message_text: Hello! I need help with my order
                      last_inbound_at: 2024-01-15T14:30:00.000000Z
                      last_outbound_at: 2024-01-15T14:25:00.000000Z
        "401":
          description: Unauthorized (invalid or missing API key)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Conversation not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/contacts:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Contacts
      summary: List contacts
      description: |
        Retrieve a paginated list of WhatsApp contacts for your project.

        Supports filtering by WhatsApp ID, customer association, and more.
      operationId: listContacts
      parameters:
        - name: wa_id
          in: query
          description: Filter by WhatsApp ID (phone number)
          schema:
            type: string
          example: "15551234567"
        - name: customer_id
          in: query
          description: Filter by associated customer ID
          schema:
            type: string
          example: cust_abc123
        - name: has_customer
          in: query
          description: Filter by customer association (true/false)
          schema:
            type: boolean
          example: true
        - name: limit
          in: query
          description: Maximum number of results per page (default 20, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: before
          in: query
          description: Cursor for previous page (Base64 encoded)
          schema:
            type: string
        - name: after
          in: query
          description: Cursor for next page (Base64 encoded)
          schema:
            type: string
        - name: fields
          in: query
          description: Filter response fields. Use `kapso()` to include Kapso-specific extensions.
          schema:
            type: string
          example: kapso()
      responses:
        "200":
          description: Successfully retrieved contacts
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WhatsappContact"
                  paging:
                    $ref: "#/components/schemas/Paging"
              examples:
                success:
                  summary: List of contacts
                  value:
                    data:
                      - id: 123e4567-e89b-12d3-a456-426614174000
                        wa_id: "15551234567"
                        profile_name: John Doe
                        display_name: John (VIP Customer)
                        metadata:
                          customer_tier: premium
                          tags:
                            - vip
                            - high-value
                        created_at: 2024-01-10T08:00:00.000000Z
                        updated_at: 2024-01-15T12:34:56.123456Z
                      - id: 223e4567-e89b-12d3-a456-426614174001
                        wa_id: "15559876543"
                        profile_name: Jane Smith
                        display_name: null
                        metadata: null
                        created_at: 2024-01-12T10:00:00.000000Z
                        updated_at: 2024-01-12T10:00:00.000000Z
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xMlQxMDowMDowMC4wMDAwMDBaIiwiMjIzZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDAxIl0sImNvbHVtbnMiOlsiY3JlYXRlZF9hdCIsImlkIl19
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/contacts/{wa_id}:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
      - name: wa_id
        in: path
        required: true
        description: WhatsApp ID (phone number)
        schema:
          type: string
        example: "15551234567"
    get:
      tags:
        - Contacts
      summary: Get contact details
      description: Retrieve detailed information about a specific contact.
      operationId: getContact
      parameters:
        - name: fields
          in: query
          description: Filter response fields
          schema:
            type: string
      responses:
        "200":
          description: Successfully retrieved contact
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WhatsappContact"
              examples:
                success:
                  summary: Contact details
                  value:
                    id: 123e4567-e89b-12d3-a456-426614174000
                    wa_id: "15551234567"
                    profile_name: John Doe
                    display_name: John (VIP Customer)
                    metadata:
                      customer_tier: premium
                      tags:
                        - vip
                        - high-value
                      last_order_date: 2024-01-10
                    created_at: 2024-01-10T08:00:00.000000Z
                    updated_at: 2024-01-15T12:34:56.123456Z
        "404":
          description: Contact not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/calls:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Calls
      summary: List calls
      description: |
        Retrieve a paginated list of WhatsApp voice calls.

        **Kapso Extension**: This endpoint returns call records stored in Kapso's database, not Meta's API.

        Supports filtering by direction, status, and time range. Uses cursor-based pagination.
      operationId: listCalls
      parameters:
        - name: direction
          in: query
          description: Filter by call direction
          schema:
            type: string
            enum:
              - inbound
              - outbound
          example: inbound
        - name: status
          in: query
          description: Filter by call status
          schema:
            type: string
            enum:
              - initiated
              - ringing
              - answered
              - completed
              - failed
          example: completed
        - name: since
          in: query
          description: Filter calls started on or after this time (ISO 8601)
          schema:
            type: string
            format: date-time
          example: 2024-01-15T00:00:00Z
        - name: until
          in: query
          description: Filter calls started on or before this time (ISO 8601)
          schema:
            type: string
            format: date-time
          example: 2024-01-15T23:59:59Z
        - name: limit
          in: query
          description: Maximum number of results per page (default 20, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
        - name: before
          in: query
          description: Cursor for previous page (Base64 encoded)
          schema:
            type: string
        - name: after
          in: query
          description: Cursor for next page (Base64 encoded)
          schema:
            type: string
        - name: fields
          in: query
          description: Filter response fields
          schema:
            type: string
      responses:
        "200":
          description: Successfully retrieved calls
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: "#/components/schemas/WhatsappCall"
                  paging:
                    $ref: "#/components/schemas/Paging"
              examples:
                success:
                  summary: List of calls
                  value:
                    data:
                      - id: 123e4567-e89b-12d3-a456-426614174000
                        call_id: call_abc123
                        direction: inbound
                        status: completed
                        duration_seconds: 180
                        started_at: 2024-01-15T12:34:56.123456Z
                        ended_at: 2024-01-15T12:37:56.123456Z
                        session_started_at: 2024-01-15T12:34:58.123456Z
                        created_at: 2024-01-15T12:34:56.000000Z
                        updated_at: 2024-01-15T12:37:56.000000Z
                        user_wa_id: "15551234567"
                        whatsapp_contact_id: 223e4567-e89b-12d3-a456-426614174001
                        whatsapp_conversation_id: 323e4567-e89b-12d3-a456-426614174002
                        project_id: 423e4567-e89b-12d3-a456-426614174003
                        whatsapp_config_id: 523e4567-e89b-12d3-a456-426614174004
                        config_display_name: Support Line
                        config_display_phone_number: +1 (555) 123-4567
                        phone_number_id: "110987654321"
                        whatsapp_contact:
                          id: 223e4567-e89b-12d3-a456-426614174001
                          wa_id: "15551234567"
                          profile_name: John Doe
                          display_name: John (VIP Customer)
                        whatsapp_conversation:
                          id: 323e4567-e89b-12d3-a456-426614174002
                          phone_number: "15551234567"
                          status: active
                          last_active_at: 2024-01-15T14:30:00.000000Z
                      - id: 724e4567-e89b-12d3-a456-426614174006
                        call_id: call_def456
                        direction: outbound
                        status: failed
                        duration_seconds: null
                        started_at: 2024-01-15T10:20:15.123456Z
                        ended_at: null
                        session_started_at: null
                        created_at: 2024-01-15T10:20:15.000000Z
                        updated_at: 2024-01-15T10:20:30.000000Z
                        user_wa_id: "15559876543"
                        whatsapp_contact_id: 824e4567-e89b-12d3-a456-426614174007
                        whatsapp_conversation_id: null
                        project_id: 423e4567-e89b-12d3-a456-426614174003
                        whatsapp_config_id: 523e4567-e89b-12d3-a456-426614174004
                        config_display_name: Support Line
                        config_display_phone_number: +1 (555) 123-4567
                        phone_number_id: "110987654321"
                        whatsapp_contact:
                          id: 824e4567-e89b-12d3-a456-426614174007
                          wa_id: "15559876543"
                          profile_name: Jane Smith
                          display_name: null
                        whatsapp_conversation: null
                    paging:
                      cursors:
                        after: eyJ2YWx1ZXMiOlsiMjAyNC0wMS0xNVQxMDoyMDoxNS4wMDAwMDBaIiwiNzI0ZTQ1NjctZTg5Yi0xMmQzLWE0NTYtNDI2NjE0MTc0MDA2Il0sImNvbHVtbnMiOlsiY2FsbF90aW1lc3RhbXAiLCJpZCJdfQ==
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Calls
      summary: Perform call action
      description: |
        Perform various call actions via the WhatsApp Calling API.

        **Proxy endpoint**: Proxies directly to Meta Graph API.

        Supports the following actions:
        - **connect**: Initiate an outbound call to a WhatsApp user
        - **pre_accept**: Pre-establish WebRTC connection before accepting call
        - **accept**: Accept an inbound call from a WhatsApp user
        - **reject**: Reject an inbound call
        - **terminate**: End an active call
      operationId: performCallAction
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - messaging_product
                - action
              properties:
                messaging_product:
                  type: string
                  enum:
                    - whatsapp
                  example: whatsapp
                to:
                  type: string
                  description: Recipient WhatsApp ID (required for connect action)
                  example: "15551234567"
                call_id:
                  type: string
                  description: Call ID (required for pre_accept, accept, reject, terminate)
                  example: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh
                action:
                  type: string
                  enum:
                    - connect
                    - pre_accept
                    - accept
                    - reject
                    - terminate
                  description: The action to perform
                  example: accept
                session:
                  type: object
                  description: WebRTC session description (required for connect, pre_accept, accept)
                  properties:
                    sdp_type:
                      type: string
                      enum:
                        - offer
                        - answer
                      description: SDP type - "offer" for connect, "answer" for pre_accept/accept
                      example: answer
                    sdp:
                      type: string
                      description: Session Description Protocol (SDP) compliant with RFC 8866
                      example: v=0\r\no=- 7669997803033704573 2 IN IP4 127.0.0.1\r\ns=-\r\n...
                biz_opaque_callback_data:
                  type: string
                  description: Arbitrary tracking string (max 512 chars, optional for connect/accept)
                  maxLength: 512
                  example: tracking_id_12345
            examples:
              initiate_call:
                summary: Initiate outbound call (connect)
                value:
                  messaging_product: whatsapp
                  to: "15551234567"
                  action: connect
                  session:
                    sdp_type: offer
                    sdp: "v=0\r

                      o=- 6314352886888624490 2 IN IP4 127.0.0.1\r

                      s=-\r

                      t=0 0\r

                      a=group:BUNDLE 0\r

                      a=extmap-allow-mixed\r

                      a=msid-semantic: WMS ccd3f422-8d7d-49c9-936c-a152979ee4fa\r

                      m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 110 126\r

                      c=IN IP4 0.0.0.0\r

                      a=rtcp:9 IN IP4 0.0.0.0\r

                      a=ice-ufrag:/PSS\r

                      a=ice-pwd:buBIz+JlbmakiCT7JdJIq/j0\r

                      a=ice-options:trickle\r

                      a=fingerprint:sha-256 43:08:34:16:67:E3:D9:A2:F5:AA:6A:AE:03:97:C8:D5:B8:F2:4B:40:79:C8:1A:44:53:69:4B:9C:89:88:D7:22\r

                      a=setup:active\r

                      a=mid:0\r

                      a=sendrecv\r

                      a=rtcp-mux\r

                      a=rtpmap:111 opus/48000/2\r\n"
                  biz_opaque_callback_data: call_session_abc123
              pre_accept_call:
                summary: Pre-accept call (establish connection early)
                value:
                  messaging_product: whatsapp
                  call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh
                  action: pre_accept
                  session:
                    sdp_type: answer
                    sdp: "v=0\r

                      o=- 7669997803033704573 2 IN IP4 127.0.0.1\r

                      s=-\r

                      t=0 0\r

                      a=group:BUNDLE 0\r

                      a=extmap-allow-mixed\r

                      a=msid-semantic: WMS 3c28addc-03b7-4170-b5cd-535bfe767e75\r

                      m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 110 126\r

                      c=IN IP4 0.0.0.0\r

                      a=rtcp:9 IN IP4 0.0.0.0\r

                      a=ice-ufrag:6O0H\r

                      a=ice-pwd:TYCbtfOrBMPpfxFRgSbYnuTI\r

                      a=setup:active\r

                      a=mid:0\r

                      a=sendrecv\r

                      a=rtcp-mux\r

                      a=rtpmap:111 opus/48000/2\r\n"
              accept_call:
                summary: Accept inbound call
                value:
                  messaging_product: whatsapp
                  call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh
                  action: accept
                  session:
                    sdp_type: answer
                    sdp: "v=0\r

                      o=- 7669997803033704573 2 IN IP4 127.0.0.1\r

                      s=-\r

                      t=0 0\r

                      a=group:BUNDLE 0\r

                      a=extmap-allow-mixed\r

                      a=msid-semantic: WMS 3c28addc-03b7-4170-b5cd-535bfe767e75\r

                      m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 110 126\r

                      c=IN IP4 0.0.0.0\r

                      a=rtcp:9 IN IP4 0.0.0.0\r

                      a=ice-ufrag:6O0H\r

                      a=ice-pwd:TYCbtfOrBMPpfxFRgSbYnuTI\r

                      a=setup:active\r

                      a=mid:0\r

                      a=sendrecv\r

                      a=rtcp-mux\r

                      a=rtpmap:111 opus/48000/2\r\n"
                  biz_opaque_callback_data: session_tracking_xyz
              reject_call:
                summary: Reject inbound call
                value:
                  messaging_product: whatsapp
                  call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh
                  action: reject
              terminate_call:
                summary: Terminate active call
                value:
                  messaging_product: whatsapp
                  call_id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh
                  action: terminate
      responses:
        "200":
          description: Action performed successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  messaging_product:
                    type: string
                    enum:
                      - whatsapp
                    example: whatsapp
                  success:
                    type: boolean
                    example: true
                  calls:
                    type: array
                    description: Returned for connect action
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          example: wacid.ABGGFjFVU2AfAgo6V
              examples:
                connect_success:
                  summary: Initiate call success
                  value:
                    messaging_product: whatsapp
                    calls:
                      - id: wacid.ABGGFjFVU2AfAgo6V-Hc5eCgK5Gh
                action_success:
                  summary: Other actions success
                  value:
                    messaging_product: whatsapp
                    success: true
        "400":
          description: Bad request (invalid action or parameters)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/media:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    post:
      tags:
        - Media
      summary: Upload media
      description: |
        Upload media files to WhatsApp. The media ID returned can be used when sending messages.

        **Supported formats and size limits:**

        **Images** (jpeg, png)
        - Max size: 5MB

        **Videos** (mp4, 3gp)
        - Max size: 16MB

        **Audio** (aac, mp3, ogg, opus)
        - Max size: 16MB

        **Documents** (pdf, doc, docx, ppt, pptx, xls, xlsx)
        - Max size: 100MB

        **Stickers** (webp)
        - Static: max 100KB
        - Animated: max 500KB
      operationId: uploadMedia
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
                - messaging_product
              properties:
                file:
                  type: string
                  format: binary
                  description: Media file to upload
                messaging_product:
                  type: string
                  enum:
                    - whatsapp
                  description: Always "whatsapp"
            examples:
              upload_image:
                summary: Upload JPEG image
                value:
                  messaging_product: whatsapp
                  file: "@/path/to/image.jpg"
              upload_video:
                summary: Upload MP4 video
                value:
                  messaging_product: whatsapp
                  file: "@/path/to/video.mp4"
              upload_audio:
                summary: Upload OGG audio
                value:
                  messaging_product: whatsapp
                  file: "@/path/to/audio.ogg"
              upload_document:
                summary: Upload PDF document
                value:
                  messaging_product: whatsapp
                  file: "@/path/to/document.pdf"
              upload_sticker:
                summary: Upload WEBP sticker
                value:
                  messaging_product: whatsapp
                  file: "@/path/to/sticker.webp"
      responses:
        "200":
          description: Media uploaded successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Media ID to use when sending messages
                    example: "4490709327384033"
              example:
                id: "4490709327384033"
        "400":
          description: Bad request (invalid file format or size exceeds limit)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{media_id}:
    parameters:
      - name: media_id
        in: path
        required: true
        description: Media ID returned from upload
        schema:
          type: string
        example: "2621233374848975"
    get:
      tags:
        - Media
      summary: Get media URL
      description: |
        Retrieve the download URL for a media file.

        **Important:** The returned URL is temporary and expires after 5 minutes.
      operationId: getMediaUrl
      parameters:
        - name: phone_number_id
          in: query
          required: true
          description: Phone number ID that owns this media
          schema:
            type: string
          example: "110987654321"
      responses:
        "200":
          description: Media URL retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  messaging_product:
                    type: string
                    enum:
                      - whatsapp
                    example: whatsapp
                  id:
                    type: string
                    description: Media ID
                    example: "2621233374848975"
                  url:
                    type: string
                    format: uri
                    description: Temporary download URL (valid for 5 minutes)
                    example: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=...
                  mime_type:
                    type: string
                    description: MIME type
                    example: image/jpeg
                  sha256:
                    type: string
                    description: File hash
                    example: 81d3bd8a8db4868c9520ed47186e8b7c5789e61ff79f7f834be6950b808a90d3
                  file_size:
                    type: string
                    description: File size in bytes (returned as string)
                    example: "303833"
                  download_url:
                    type: string
                    format: uri
                    description: |
                      Kapso-hosted authenticated download URL. Valid for 4 minutes.
                      Use this URL to download the media file without needing to pass auth headers — authentication is embedded in the token.
                    example: https://api.kapso.ai/meta/whatsapp/media_download?token=...
                  download_url_expires_at:
                    type: string
                    format: date-time
                    description: ISO 8601 expiry timestamp for `download_url`.
                    example: 2026-03-13T12:34:56Z
              example:
                messaging_product: whatsapp
                url: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=2621233374848975&ext=1234567890&hash=...
                mime_type: image/jpeg
                sha256: 81d3bd8a8db4868c9520ed47186e8b7c5789e61ff79f7f834be6950b808a90d3
                file_size: "303833"
                id: "2621233374848975"
                download_url: https://api.kapso.ai/meta/whatsapp/media_download?token=eyJfcmFpbHMiOnsibWVzc2FnZSI6...
                download_url_expires_at: 2026-03-13T12:34:56Z
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Media not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - Media
      summary: Delete media
      description: |
        Delete a media file from WhatsApp.

        You can optionally provide `phone_number_id` query parameter to verify the media belongs to that phone number before deletion.
      operationId: deleteMedia
      parameters:
        - name: phone_number_id
          in: query
          required: false
          description: Optional - verify media belongs to this phone number
          schema:
            type: string
          example: "110987654321"
      responses:
        "200":
          description: Media deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Media not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /media_download:
    servers:
      - url: https://api.kapso.ai/meta/whatsapp
        description: Kapso Media Download (no version prefix)
    get:
      tags:
        - Media
      summary: Download media file
      description: |
        Download a media file using a short-lived authenticated token.

        Tokens are returned in the `download_url` field of the [Get media URL](#operation/getMediaUrl) response.
        They expire 4 minutes after issue.

        No `X-API-Key` header is needed — authentication is embedded in the token.
      operationId: downloadMedia
      parameters:
        - name: token
          in: query
          required: true
          description: Signed token from `download_url`
          schema:
            type: string
          example: eyJfcmFpbHMiOnsibWVzc2FnZSI6...
      responses:
        "200":
          description: Media file bytes
          headers:
            Content-Type:
              description: MIME type of the media file
              schema:
                type: string
                example: image/jpeg
            Content-Disposition:
              description: Inline disposition with media ID as filename
              schema:
                type: string
                example: inline; filename="2621233374848975"
            Cache-Control:
              description: Cache directive (tokens are short-lived)
              schema:
                type: string
                example: private, max-age=240
          content:
            application/octet-stream:
              schema:
                type: string
                format: binary
        "404":
          description: Token missing, invalid, expired, or media not found
        "502":
          description: Media download from WhatsApp failed
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Media download failed
  /{business_account_id}/message_templates:
    parameters:
      - name: business_account_id
        in: path
        required: true
        description: WhatsApp Business Account ID
        schema:
          type: string
        example: "123456789012345"
    get:
      tags:
        - Templates
      summary: List message templates
      description: |
        Retrieve a list of approved message templates for this phone number.

        Templates must be approved by WhatsApp before they can be used.
      operationId: listTemplates
      parameters:
        - name: name
          in: query
          description: Filter by template name
          schema:
            type: string
          example: order_confirmation
        - name: status
          in: query
          description: Filter by template status
          schema:
            type: string
            enum:
              - APPROVED
              - PENDING
              - REJECTED
          example: APPROVED
        - name: category
          in: query
          description: Filter by template category
          schema:
            type: string
            enum:
              - AUTHENTICATION
              - MARKETING
              - UTILITY
        - name: language
          in: query
          description: Filter by language code
          schema:
            type: string
          example: en_US
        - name: limit
          in: query
          description: Maximum number of results (default 20, max 100)
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
      responses:
        "200":
          description: Successfully retrieved templates
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Template ID
                          example: "1192339204654487"
                        name:
                          type: string
                          example: order_confirmation
                        language:
                          type: string
                          example: en_US
                        status:
                          type: string
                          enum:
                            - APPROVED
                            - PENDING
                            - REJECTED
                          example: APPROVED
                        category:
                          type: string
                          enum:
                            - AUTHENTICATION
                            - MARKETING
                            - UTILITY
                          example: UTILITY
                        previous_category:
                          type: string
                          description: Previous category if changed
                          example: ACCOUNT_UPDATE
                        components:
                          type: array
                          description: Template components (header, body, footer, buttons)
                  paging:
                    $ref: "#/components/schemas/Paging"
              example:
                data:
                  - id: "1192339204654487"
                    name: hello_world
                    previous_category: ACCOUNT_UPDATE
                    components:
                      - type: HEADER
                        format: TEXT
                        text: Hello World
                      - type: BODY
                        text: Welcome and congratulations!! This message demonstrates your ability to send a message notification from WhatsApp Business Platform's Cloud API. Thank you for taking the time to test with us.
                      - type: FOOTER
                        text: WhatsApp Business API Team
                    language: en_US
                    status: APPROVED
                    category: MARKETING
                  - id: "920070352646140"
                    name: seasonal_promotion
                    components:
                      - type: HEADER
                        format: TEXT
                        text: Fall Sale
                      - type: BODY
                        text: Hi {{1}}, our Fall Sale is on! Use promo code {{2}} Get an extra 25% off every order above $350!
                        example:
                          body_text:
                            - - Mark
                              - FALL25
                      - type: FOOTER
                        text: Not interested in any of our sales? Tap Stop Promotions
                      - type: BUTTONS
                        buttons:
                          - type: QUICK_REPLY
                            text: Stop promotions
                    language: en_US
                    status: APPROVED
                    category: MARKETING
                paging:
                  cursors:
                    before: MAZDZD
                    after: MjQZD
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Templates
      summary: Create or update message template
      description: |
        Create a new WhatsApp message template, or update an existing one.

        - Omit `hsm_id` to create a new template.
        - Include `hsm_id` as a query parameter to update an existing template.

        Templates must be approved by WhatsApp before they can be used. After creation,
        templates enter a PENDING state until reviewed.

        **Side effect**: Enqueues a template sync job on success to update Kapso's
        local template cache.
      operationId: createOrUpdateTemplate
      parameters:
        - name: hsm_id
          in: query
          required: false
          description: |
            Template ID to update.

            - Omit for template creation.
            - Required when updating an existing template.
          schema:
            type: string
          example: "1627019861106475"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: |
                Request body for template creation or update.

                - For create requests, `name`, `language`, `category`, and `components`
                  are required.
                - For update requests, include `hsm_id` in the query string and provide
                  the fields you want to change.
              properties:
                name:
                  type: string
                  description: Template name (lowercase, underscore-separated)
                  example: order_confirmation
                language:
                  type: string
                  description: Language code (e.g., en, en_US)
                  example: en_US
                category:
                  type: string
                  enum:
                    - AUTHENTICATION
                    - MARKETING
                    - UTILITY
                  description: Template category
                  example: UTILITY
                parameter_format:
                  type: string
                  enum:
                    - NAMED
                    - POSITIONAL
                  description: |
                    Format for template parameters (defaults to POSITIONAL if omitted).

                    **NAMED**: Parameters use unique names wrapped in double curly brackets (e.g., {{first_name}}, {{order_number}}). Values can appear in any order in send payloads.

                    **POSITIONAL**: Parameters use ordered array indices starting from 1 (e.g., {{1}}, {{2}}). Values must appear in order in send payloads.
                  example: NAMED
                components:
                  type: array
                  description: |
                    Template components. Supported types:

                    **HEADER** - Optional component at top. Formats: TEXT (1 param), IMAGE, VIDEO, DOCUMENT, LOCATION

                    **BODY** - Required text component. Supports multiple parameters (positional or named)

                    **FOOTER** - Optional text-only component. No parameters supported

                    **BUTTONS** - Optional interactive components. Types: QUICK_REPLY (10 max), PHONE_NUMBER (1 max), URL (2 max), COPY_CODE (1 max), OTP, CATALOG, MPM, FLOW
                  items:
                    type: object
            examples:
              body_named_params:
                summary: Simple body with named parameters (simplest)
                value:
                  name: order_confirmation_simple
                  language: en_US
                  category: UTILITY
                  parameter_format: NAMED
                  components:
                    - type: BODY
                      text: Thank you, {{customer_name}}! Your order number is {{order_number}}.
                      example:
                        body_text_named_params:
                          - param_name: customer_name
                            example: Pablo
                          - param_name: order_number
                            example: 860198-230332
              body_positional_params:
                summary: Body with positional parameters
                value:
                  name: delivery_notification
                  language: en_US
                  category: UTILITY
                  parameter_format: POSITIONAL
                  components:
                    - type: BODY
                      text: "Good news {{1}}! Your order #{{2}} has been delivered."
                      example:
                        body_text:
                          - - Mark
                            - "566701"
              text_header_body_footer_buttons:
                summary: Text header + body + footer + quick reply buttons
                value:
                  name: seasonal_promotion
                  language: en_US
                  category: MARKETING
                  components:
                    - type: HEADER
                      format: TEXT
                      text: Our {{1}} is on!
                      example:
                        header_text:
                          - Summer Sale
                    - type: BODY
                      text: Shop now through {{1}} and use code {{2}} to get {{3}} off of all merchandise.
                      example:
                        body_text:
                          - - the end of August
                            - 25OFF
                            - 25%
                    - type: FOOTER
                      text: Use the buttons below to manage your marketing subscriptions
                    - type: BUTTONS
                      buttons:
                        - type: QUICK_REPLY
                          text: Unsubscribe from Promos
                        - type: QUICK_REPLY
                          text: Unsubscribe from All
              document_header:
                summary: Document header with action buttons
                value:
                  name: order_confirmation_receipt
                  language: en_US
                  category: UTILITY
                  components:
                    - type: HEADER
                      format: DOCUMENT
                      example:
                        header_handle:
                          - 4::YXBwbGljYXRpb24vcGRm:ARZVv4zuogJMxmAdS3_6T4o...
                    - type: BODY
                      text: Thank you for your order, {{1}}! Your order number is {{2}}. Tap the PDF linked above to view your receipt. If you have any questions, please use the buttons below to contact support.
                      example:
                        body_text:
                          - - Pablo
                            - 860198-230332
                    - type: BUTTONS
                      buttons:
                        - type: PHONE_NUMBER
                          text: Call
                          phone_number: "15550051310"
                        - type: URL
                          text: Contact Support
                          url: https://www.luckyshrub.com/support
              location_header:
                summary: Location header for delivery/pickup
                value:
                  name: order_delivery_update
                  language: en_US
                  category: UTILITY
                  components:
                    - type: HEADER
                      format: LOCATION
                    - type: BODY
                      text: "Good news {{1}}! Your order #{{2}} is on its way to the location above. Thank you for your order!"
                      example:
                        body_text:
                          - - Mark
                            - "566701"
                    - type: FOOTER
                      text: To stop receiving delivery updates, tap the button below.
                    - type: BUTTONS
                      buttons:
                        - type: QUICK_REPLY
                          text: Stop Delivery Updates
              image_header:
                summary: Image header with media
                value:
                  name: limited_time_offer
                  language: en_US
                  category: MARKETING
                  components:
                    - type: HEADER
                      format: IMAGE
                      example:
                        header_handle:
                          - 4::aW1hZ2UvanBlZw==:ARa1ZDhwbLZM3EENeeg
                    - type: BODY
                      text: Hi {{1}}! For a limited time only you can get our {{2}} for as low as {{3}}.
                      example:
                        body_text:
                          - - Mark
                            - Tuscan Getaway package
                            - "800"
                    - type: FOOTER
                      text: Offer valid until May 31, 2023
                    - type: BUTTONS
                      buttons:
                        - type: PHONE_NUMBER
                          text: Call
                          phone_number: "15550051310"
                        - type: URL
                          text: Shop Now
                          url: https://www.examplesite.com/shop
              url_button_with_param:
                summary: URL button with dynamic parameter
                value:
                  name: promo_with_dynamic_link
                  language: en_US
                  category: MARKETING
                  components:
                    - type: BODY
                      text: Special offer just for you! Tap below to view your personalized deals.
                    - type: BUTTONS
                      buttons:
                        - type: URL
                          text: View Offers
                          url: https://www.examplesite.com/shop?promo={{1}}
                          example:
                            - summer2023
              authentication_otp_copy_code:
                summary: Authentication - COPY_CODE (manual entry)
                value:
                  name: auth_otp_copy_code
                  language: en_US
                  category: AUTHENTICATION
                  components:
                    - type: BODY
                      add_security_recommendation: true
                    - type: FOOTER
                      code_expiration_minutes: 10
                    - type: BUTTONS
                      buttons:
                        - type: OTP
                          otp_type: COPY_CODE
              authentication_otp_one_tap:
                summary: Authentication - ONE_TAP (Android autofill)
                value:
                  name: auth_otp_one_tap
                  language: en_US
                  category: AUTHENTICATION
                  components:
                    - type: BODY
                      add_security_recommendation: true
                    - type: FOOTER
                      code_expiration_minutes: 10
                    - type: BUTTONS
                      buttons:
                        - type: OTP
                          otp_type: ONE_TAP
                          supported_apps:
                            - package_name: com.example.myapp
                              signature_hash: K8a%2FAINcGX7
              authentication_otp_zero_tap:
                summary: Authentication - ZERO_TAP (no button, auto-read)
                value:
                  name: auth_otp_zero_tap
                  language: en_US
                  category: AUTHENTICATION
                  components:
                    - type: BODY
                      add_security_recommendation: false
                    - type: FOOTER
                      code_expiration_minutes: 5
                    - type: BUTTONS
                      buttons:
                        - type: OTP
                          otp_type: ZERO_TAP
              catalog_button:
                summary: Catalog button for product browsing
                value:
                  name: catalog_promotion
                  language: en_US
                  category: MARKETING
                  components:
                    - type: BODY
                      text: Now shop for your favourite products right here on WhatsApp! Get Rs {{1}} off on all orders above {{2}}Rs!
                      example:
                        body_text:
                          - - "100"
                            - "400"
                    - type: FOOTER
                      text: Best grocery deals on WhatsApp!
                    - type: BUTTONS
                      buttons:
                        - type: CATALOG
                          text: View catalog
              mpm_button:
                summary: Multi-product message button
                value:
                  name: abandoned_cart_mpm
                  language: en_US
                  category: MARKETING
                  components:
                    - type: HEADER
                      format: TEXT
                      text: Forget something {{1}}?
                      example:
                        header_text:
                          - Pablo
                    - type: BODY
                      text: Looks like you left some items in your cart! Use code {{1}} and you can get 10% off of all of them!
                      example:
                        body_text:
                          - - 10OFF
                    - type: BUTTONS
                      buttons:
                        - type: MPM
                          text: View items
              video_header:
                summary: Video header with media
                value:
                  name: product_demo_video
                  language: en_US
                  category: MARKETING
                  components:
                    - type: HEADER
                      format: VIDEO
                      example:
                        header_handle:
                          - 4::dmlkZW8vbXA0:ARa8f2Xh9K3pLmNqR1sT...
                    - type: BODY
                      text: Check out our new product in action! Watch the video above to see how it works.
                    - type: FOOTER
                      text: Available now
              text_header_named_params:
                summary: Text header with named parameters
                value:
                  name: event_reminder
                  language: en_US
                  category: UTILITY
                  components:
                    - type: HEADER
                      format: TEXT
                      text: "Reminder: {{event_name}} starts {{start_time}}"
                      example:
                        header_text_named_params:
                          - param_name: event_name
                            example: Summer Webinar
                          - param_name: start_time
                            example: tomorrow at 3 PM
                    - type: BODY
                      text: Don't forget to join us for {{event_name}}. We'll be covering exciting updates!
                      example:
                        body_text_named_params:
                          - param_name: event_name
                            example: Summer Webinar
              copy_code_button:
                summary: Copy code button for promo codes
                value:
                  name: promo_code_offer
                  language: en_US
                  category: MARKETING
                  components:
                    - type: BODY
                      text: Special discount just for you! Use code below to get 20% off your next purchase.
                    - type: BUTTONS
                      buttons:
                        - type: COPY_CODE
                          example: SAVE20
              flow_button_basic:
                summary: Flow button for interactive experiences
                value:
                  name: feedback_survey_flow
                  language: en_US
                  category: UTILITY
                  components:
                    - type: BODY
                      text: We'd love to hear your feedback! Tap below to share your thoughts in a quick survey.
                    - type: BUTTONS
                      buttons:
                        - type: FLOW
                          text: Take Survey
                          flow_id: "123456789012345"
                          flow_action: navigate
                          navigate_screen: WELCOME_SCREEN
              template_update:
                summary: Update an existing template by hsm_id
                value:
                  category: MARKETING
                  components:
                    - type: HEADER
                      format: TEXT
                      text: Updated Header
                    - type: BODY
                      text: Updated body text
      responses:
        "200":
          description: Template created or updated successfully
          content:
            application/json:
              schema:
                oneOf:
                  - type: object
                    properties:
                      id:
                        type: string
                        description: Template ID
                        example: "1627019861106475"
                      status:
                        type: string
                        enum:
                          - PENDING
                          - APPROVED
                          - REJECTED
                        description: Template status
                        example: PENDING
                      category:
                        type: string
                        description: Template category
                        example: UTILITY
                  - type: object
                    properties:
                      success:
                        type: boolean
                        example: true
              examples:
                created:
                  summary: Template created
                  value:
                    id: "1627019861106475"
                    status: PENDING
                    category: UTILITY
                updated:
                  summary: Template updated
                  value:
                    success: true
        "400":
          description: Bad request (invalid template format or missing/invalid hsm_id for updates)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/Error"
                  - type: object
                    required:
                      - error
                    properties:
                      error:
                        type: string
                        example: hsm_id is required
              examples:
                invalid_template:
                  summary: Invalid template format
                  value:
                    error:
                      message: Invalid template format
                      type: OAuthException
                      code: 400
                missing_hsm_id:
                  summary: Missing hsm_id on update
                  value:
                    error: hsm_id is required
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Template not found (update only)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - Templates
      summary: Delete message template
      description: |
        Delete a WhatsApp message template.

        **Specify either `name` or `hsm_id` to identify the template to delete.**
      operationId: deleteTemplate
      parameters:
        - name: name
          in: query
          required: false
          description: Template name to delete (use this OR hsm_id)
          schema:
            type: string
          example: order_confirmation
        - name: hsm_id
          in: query
          required: false
          description: Template ID to delete (use this OR name)
          schema:
            type: string
          example: "1627019861106475"
      responses:
        "200":
          description: Template deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        "404":
          description: Template not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{business_account_id}/message_templates/{template_id}:
    parameters:
      - name: business_account_id
        in: path
        required: true
        description: WhatsApp Business Account ID
        schema:
          type: string
        example: "123456789012345"
      - name: template_id
        in: path
        required: true
        description: Template ID
        schema:
          type: string
        example: "1259544702043867"
    get:
      tags:
        - Templates
      summary: Get message template by ID
      description: |
        Retrieve a single WhatsApp message template by its ID.

        Use this endpoint to fetch full details of a specific template when you already know its ID. For listing templates or searching by name, use the list endpoint instead.
      operationId: getTemplate
      parameters:
        - name: fields
          in: query
          description: Comma-separated list of fields to retrieve
          schema:
            type: string
          example: id,name,status,language,components
      responses:
        "200":
          description: Successfully retrieved template
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Template ID
                    example: "1259544702043867"
                  name:
                    type: string
                    example: order_confirmation
                  language:
                    type: string
                    example: en_US
                  status:
                    type: string
                    enum:
                      - APPROVED
                      - PENDING
                      - REJECTED
                    example: APPROVED
                  category:
                    type: string
                    enum:
                      - AUTHENTICATION
                      - MARKETING
                      - UTILITY
                    example: UTILITY
                  previous_category:
                    type: string
                    description: Previous category if changed
                    example: ACCOUNT_UPDATE
                  components:
                    type: array
                    description: Template components (header, body, footer, buttons)
                    items:
                      type: object
              example:
                id: "1259544702043867"
                name: order_confirmation
                language: en_US
                status: APPROVED
                category: UTILITY
                components:
                  - type: HEADER
                    format: TEXT
                    text: Order Update
                  - type: BODY
                    text: Your order {{1}} has been confirmed and will arrive by {{2}}.
                    example:
                      body_text:
                        - - "#12345"
                          - Friday
                  - type: FOOTER
                    text: Thanks for shopping with us!
        "400":
          description: Bad request (invalid template_id format)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              example:
                error: invalid template_id
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "404":
          description: Template not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/whatsapp_business_profile:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Business Profile
      summary: Get business profile
      description: |
        Retrieve the WhatsApp Business profile information. WhatsApp users can view your business profile by clicking your business's name or number in a WhatsApp message thread.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: getBusinessProfile
      parameters:
        - name: fields
          in: query
          required: false
          description: Comma-separated list of fields to retrieve
          schema:
            type: string
          example: about,address,description,email,profile_picture_url,websites,vertical
      responses:
        "200":
          description: Profile retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        about:
                          type: string
                          description: The business's About text (1-139 characters). Appears in profile beneath profile image and phone number.
                          minLength: 1
                          maxLength: 139
                        address:
                          type: string
                          description: Address of the business
                          maxLength: 256
                        description:
                          type: string
                          description: Description of the business
                          maxLength: 512
                        email:
                          type: string
                          format: email
                          description: Contact email address of the business
                          maxLength: 128
                        messaging_product:
                          type: string
                          description: Messaging service (always "whatsapp")
                          enum:
                            - whatsapp
                        profile_picture_url:
                          type: string
                          format: uri
                          description: URL of the profile picture (read-only)
                          readOnly: true
                        websites:
                          type: array
                          description: URLs associated with the business (max 2 websites, 256 chars each)
                          maxItems: 2
                          items:
                            type: string
                            format: uri
                            maxLength: 256
                        vertical:
                          type: string
                          description: Business industry category
                          enum:
                            - ALCOHOL
                            - APPAREL
                            - AUTO
                            - BEAUTY
                            - EDU
                            - ENTERTAIN
                            - EVENT_PLAN
                            - FINANCE
                            - GROCERY
                            - GOVT
                            - HOTEL
                            - HEALTH
                            - NONPROFIT
                            - ONLINE_GAMBLING
                            - OTC_DRUGS
                            - OTHER
                            - PHYSICAL_GAMBLING
                            - PROF_SERVICES
                            - RESTAURANT
                            - RETAIL
                            - TRAVEL
              example:
                data:
                  - about: Premium coffee roasters since 2010
                    address: 123 Main St, San Francisco, CA 94102
                    description: Specialty coffee beans sourced directly from sustainable farms
                    email: hello@premiumcoffee.com
                    messaging_product: whatsapp
                    profile_picture_url: https://lookaside.fbsbx.com/whatsapp_business/attachments/?mid=...
                    websites:
                      - https://premiumcoffee.com
                      - https://instagram.com/premiumcoffee
                    vertical: RETAIL
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Business Profile
      summary: Update business profile
      description: |
        Update WhatsApp business profile information.

        **Proxy endpoint**: Proxies directly to Meta Graph API /PHONE_NUMBER_ID/whatsapp_business_profile.

        Use this endpoint to update:
        - About text (1-139 characters, appears below profile image)
        - Business address and description
        - Contact email
        - Profile picture (via handle from resumable upload)
        - Business category (vertical)
        - Website links (max 2)

        **Restrictions**:
        - About text: 1-139 chars, rendered emojis supported, hyperlinks won't be clickable, no markdown
        - Address: max 256 characters
        - Description: max 512 characters
        - Email: max 128 characters, valid email format
        - Websites: max 2 URLs, max 256 chars each, must include http:// or https://

        **Note**: Sandbox configurations are blocked (returns 403).
      operationId: updateBusinessProfile
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/BusinessProfileUpdate"
            examples:
              basic_about:
                summary: Update About text
                value:
                  messaging_product: whatsapp
                  about: Welcome to our store! We're here to help you 24/7 with all your shopping needs.
              complete_profile:
                summary: Update all profile fields
                value:
                  messaging_product: whatsapp
                  about: Your trusted partner for quality products and services.
                  address: 123 Main Street, San Francisco, CA 94102
                  description: Leading provider of premium products and services since 2010. We pride ourselves on exceptional customer service and quality.
                  email: support@example.com
                  vertical: RETAIL
                  websites:
                    - https://www.example.com
                    - https://www.instagram.com/example
              with_profile_picture:
                summary: Update profile with picture
                description: Profile picture handle from resumable upload API
                value:
                  messaging_product: whatsapp
                  about: Premium spa and beauty services
                  vertical: BEAUTY
                  profile_picture_handle: h:resumable-upload-handle-abc123xyz789
              restaurant:
                summary: Restaurant profile
                value:
                  messaging_product: whatsapp
                  about: Authentic Italian cuisine in the heart of SF
                  address: 456 Market Street, San Francisco, CA 94103
                  description: Family-owned Italian restaurant serving traditional recipes passed down through generations. Reservations recommended.
                  email: reservations@restaurant.com
                  vertical: RESTAURANT
                  websites:
                    - https://www.restaurant.com
      responses:
        "200":
          description: Business profile updated successfully
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/BusinessProfileUpdateResponse"
              examples:
                success:
                  summary: Successful update
                  value:
                    success: true
        "400":
          description: Bad request (validation errors)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                invalid_about_length:
                  summary: About text too long
                  value:
                    error:
                      message: About text must be between 1 and 139 characters
                      type: OAuthException
                      code: 400
                invalid_email:
                  summary: Invalid email format
                  value:
                    error:
                      message: Invalid email address format
                      type: OAuthException
                      code: 400
                too_many_websites:
                  summary: Too many URLs
                  value:
                    error:
                      message: Maximum of 2 websites allowed
                      type: OAuthException
                      code: 400
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "403":
          description: Forbidden (sandbox configs blocked)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
              examples:
                sandbox_blocked:
                  summary: Sandbox configuration rejected
                  value:
                    error:
                      message: Sandbox WhatsApp configurations cannot update business profile
                      type: OAuthException
                      code: 403
        "404":
          description: Phone number not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/call_permissions:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Calls
      summary: Get call permission state
      description: |
        Get the call permission state for a business phone number with a specific WhatsApp user.

        **Proxy endpoint**: Proxies directly to Meta Graph API.

        Returns the current permission status and available actions with their limits. Permission can be:
        - **no_permission**: No calling permission granted
        - **temporary**: Temporary permission with expiration time

        Actions include:
        - **send_call_permission_request**: Send permission request message
        - **start_call**: Initiate a call

        Each action has time-based limits (e.g., max 2 permission requests per 24 hours).
      operationId: getCallPermissions
      parameters:
        - name: user_wa_id
          in: query
          required: true
          description: WhatsApp ID of the user (phone number)
          schema:
            type: string
          example: "15551234567"
      responses:
        "200":
          description: Permissions retrieved successfully
          content:
            application/json:
              schema:
                type: object
                required:
                  - messaging_product
                  - permission
                  - actions
                properties:
                  messaging_product:
                    type: string
                    enum:
                      - whatsapp
                    example: whatsapp
                  permission:
                    type: object
                    required:
                      - status
                    properties:
                      status:
                        type: string
                        enum:
                          - no_permission
                          - temporary
                        description: Current permission status
                        example: temporary
                      expiration_time:
                        type: integer
                        description: Unix timestamp when permission expires (only for temporary status)
                        example: 1745343479
                  actions:
                    type: array
                    description: Available actions with their limits
                    items:
                      type: object
                      properties:
                        action_name:
                          type: string
                          enum:
                            - send_call_permission_request
                            - start_call
                          description: The action that can be performed
                          example: send_call_permission_request
                        can_perform_action:
                          type: boolean
                          description: Whether the action can be performed now
                          example: true
                        limits:
                          type: array
                          description: Time-based restrictions for this action
                          items:
                            type: object
                            properties:
                              time_period:
                                type: string
                                description: Time span in ISO 8601 format (e.g., PT24H for 24 hours, P7D for 7 days)
                                example: PT24H
                              max_allowed:
                                type: integer
                                description: Maximum actions allowed in this time period
                                example: 1
                              current_usage:
                                type: integer
                                description: Current number of actions taken in this period
                                example: 0
                              limit_expiration_time:
                                type: integer
                                description: Unix timestamp when limit resets (only present when limit is reached)
                                example: 1745622600
              examples:
                temporary_permission:
                  summary: Temporary permission granted
                  value:
                    messaging_product: whatsapp
                    permission:
                      status: temporary
                      expiration_time: 1745343479
                    actions:
                      - action_name: send_call_permission_request
                        can_perform_action: true
                        limits:
                          - time_period: PT24H
                            max_allowed: 1
                            current_usage: 0
                          - time_period: P7D
                            max_allowed: 2
                            current_usage: 1
                      - action_name: start_call
                        can_perform_action: false
                        limits:
                          - time_period: PT24H
                            max_allowed: 5
                            current_usage: 5
                            limit_expiration_time: 1745622600
                no_permission:
                  summary: No permission granted
                  value:
                    messaging_product: whatsapp
                    permission:
                      status: no_permission
                    actions:
                      - action_name: send_call_permission_request
                        can_perform_action: true
                        limits:
                          - time_period: PT24H
                            max_allowed: 1
                            current_usage: 0
                      - action_name: start_call
                        can_perform_action: false
                        limits: []
        "400":
          description: Bad request (invalid parameters)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "429":
          description: Rate limit reached (max 5 requests per second)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/block_users:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
        example: "110987654321"
    get:
      tags:
        - Block Users
      summary: List blocked users
      description: |
        Retrieve the list of users blocked for a given phone number.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: listBlockedUsers
      responses:
        "200":
          description: Blocked users retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        user:
                          type: string
                          description: WhatsApp ID (phone number) of the blocked user
                          example: "15551234567"
              examples:
                success:
                  summary: List of blocked users
                  value:
                    data:
                      - user: "15551234567"
                      - user: "15559876543"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Block Users
      summary: Block users
      description: |
        Block one or more users for a given phone number.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: blockUsers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - block_users
              properties:
                block_users:
                  type: array
                  items:
                    type: object
                    required:
                      - user
                    properties:
                      user:
                        type: string
                        description: WhatsApp ID (phone number) of the user to block
                        example: "15551234567"
            example:
              block_users:
                - user: "15551234567"
                - user: "15559876543"
      responses:
        "200":
          description: Users blocked successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    delete:
      tags:
        - Block Users
      summary: Unblock users
      description: |
        Unblock one or more previously blocked users for a given phone number.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: unblockUsers
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - block_users
              properties:
                block_users:
                  type: array
                  items:
                    type: object
                    required:
                      - user
                    properties:
                      user:
                        type: string
                        description: WhatsApp ID (phone number) of the user to unblock
                        example: "15551234567"
            example:
              block_users:
                - user: "15551234567"
      responses:
        "200":
          description: Users unblocked successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
        "400":
          description: Bad request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{business_account_id}/flows:
    parameters:
      - name: business_account_id
        in: path
        required: true
        description: WhatsApp Business Account ID
        schema:
          type: string
    get:
      tags:
        - Flows
      summary: List flows
      description: |
        List all WhatsApp Flows for a business account.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: listFlows
      responses:
        "200":
          description: Flows retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                          enum:
                            - DRAFT
                            - PUBLISHED
                            - DEPRECATED
                            - BLOCKED
                            - THROTTLED
                        categories:
                          type: array
                          items:
                            type: string
                        validation_errors:
                          type: array
                          items:
                            type: object
                            properties:
                              error:
                                type: string
                                example: INVALID_PROPERTY
                              error_type:
                                type: string
                                example: JSON_SCHEMA_ERROR
                              message:
                                type: string
                                example: The property "initial-text" cannot be specified at "$root/screens/0/layout/children/2/children/0".
                              line_start:
                                type: integer
                              line_end:
                                type: integer
                              column_start:
                                type: integer
                              column_end:
                                type: integer
                  paging:
                    $ref: "#/components/schemas/Paging"
              example:
                data:
                  - id: flow-1
                    name: my first flow
                    status: DRAFT
                    categories:
                      - SIGN_UP
                    validation_errors: []
                  - id: flow-2
                    name: my second flow
                    status: PUBLISHED
                    categories:
                      - SURVEY
                    validation_errors: []
                paging:
                  cursors:
                    before: QVFIUnpKT...
                    after: QVFIUnZAWV...
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Flows
      summary: Create flow
      description: |
        Create a new WhatsApp Flow.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: createFlow
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - categories
              properties:
                name:
                  type: string
                  description: Flow name
                categories:
                  type: array
                  items:
                    type: string
                    enum:
                      - SIGN_UP
                      - SIGN_IN
                      - APPOINTMENT_BOOKING
                      - LEAD_GENERATION
                      - CONTACT_US
                      - CUSTOMER_SUPPORT
                      - SURVEY
                      - OTHER
                  description: Flow categories
                clone_flow_id:
                  type: string
                  description: ID of flow to clone
                endpoint_uri:
                  type: string
                  format: uri
                  description: Endpoint URI for the flow
                flow_json:
                  type: string
                  description: Flow's JSON encoded as string. If provided with publish=true, creates and publishes flow in one request.
                publish:
                  type: boolean
                  description: Indicates whether Flow should also get published. Only works if flow_json is provided with valid Flow JSON.
            example:
              name: appointment_booking
              categories:
                - APPOINTMENT_BOOKING
      responses:
        "200":
          description: Flow created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Flow ID
                  success:
                    type: boolean
                  validation_errors:
                    type: array
                    items:
                      type: object
                      properties:
                        error:
                          type: string
                        error_type:
                          type: string
                        message:
                          type: string
                        line_start:
                          type: integer
                        line_end:
                          type: integer
                        column_start:
                          type: integer
                        column_end:
                          type: integer
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}/flows:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
    get:
      tags:
        - Flows
      summary: List flows (phone number scoped)
      description: |
        List all WhatsApp Flows for a phone number.

        **Proxy endpoint**: Proxies directly to Meta Graph API.

        **Note**: Requires WhatsappConfig with matching phone_number_id.
      operationId: listFlowsByPhoneNumber
      responses:
        "200":
          description: Flows retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                          enum:
                            - DRAFT
                            - PUBLISHED
                            - DEPRECATED
                            - BLOCKED
                            - THROTTLED
                        categories:
                          type: array
                          items:
                            type: string
                        validation_errors:
                          type: array
                          items:
                            type: object
                            properties:
                              error:
                                type: string
                                example: INVALID_PROPERTY
                              error_type:
                                type: string
                                example: JSON_SCHEMA_ERROR
                              message:
                                type: string
                                example: The property "initial-text" cannot be specified at "$root/screens/0/layout/children/2/children/0".
                              line_start:
                                type: integer
                              line_end:
                                type: integer
                              column_start:
                                type: integer
                              column_end:
                                type: integer
                  paging:
                    $ref: "#/components/schemas/Paging"
              example:
                data:
                  - id: flow-1
                    name: my first flow
                    status: DRAFT
                    categories:
                      - SIGN_UP
                    validation_errors: []
                  - id: flow-2
                    name: my second flow
                    status: PUBLISHED
                    categories:
                      - SURVEY
                    validation_errors: []
                paging:
                  cursors:
                    before: QVFIUnpKT...
                    after: QVFIUnZAWV...
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Flows
      summary: Create flow (phone number scoped)
      description: |
        Create a new WhatsApp Flow for a phone number.

        **Proxy endpoint**: Proxies directly to Meta Graph API.

        **Note**: Requires WhatsappConfig with matching phone_number_id.
      operationId: createFlowByPhoneNumber
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - name
                - categories
              properties:
                name:
                  type: string
                  description: Flow name
                categories:
                  type: array
                  items:
                    type: string
                    enum:
                      - SIGN_UP
                      - SIGN_IN
                      - APPOINTMENT_BOOKING
                      - LEAD_GENERATION
                      - CONTACT_US
                      - CUSTOMER_SUPPORT
                      - SURVEY
                      - OTHER
                  description: Flow categories
                clone_flow_id:
                  type: string
                  description: ID of flow to clone
                endpoint_uri:
                  type: string
                  format: uri
                  description: Endpoint URI for the flow
                flow_json:
                  type: string
                  description: Flow's JSON encoded as string. If provided with publish=true, creates and publishes flow in one request.
                publish:
                  type: boolean
                  description: Indicates whether Flow should also get published. Only works if flow_json is provided with valid Flow JSON.
            example:
              name: appointment_booking
              categories:
                - APPOINTMENT_BOOKING
      responses:
        "200":
          description: Flow created successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Flow ID
                  success:
                    type: boolean
                  validation_errors:
                    type: array
                    items:
                      type: object
                      properties:
                        error:
                          type: string
                        error_type:
                          type: string
                        message:
                          type: string
                        line_start:
                          type: integer
                        line_end:
                          type: integer
                        column_start:
                          type: integer
                        column_end:
                          type: integer
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{flow_id}/assets:
    parameters:
      - name: flow_id
        in: path
        required: true
        description: Flow ID
        schema:
          type: string
    get:
      tags:
        - Flows
      summary: Get flow assets
      description: |
        Get flow JSON assets and URLs.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: getFlowAssets
      responses:
        "200":
          description: Flow assets retrieved
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                          description: Asset name (always "flow.json")
                          example: flow.json
                        asset_type:
                          type: string
                          description: Asset type (always "FLOW_JSON")
                          example: FLOW_JSON
                        download_url:
                          type: string
                          format: uri
                          description: URL to download the flow JSON file
                          example: https://scontent.xx.fbcdn.net/m1/v/t0.57323-24/An_Hq0jnfJ...
                  paging:
                    $ref: "#/components/schemas/Paging"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Flows
      summary: Upload flow JSON
      description: |
        Upload or update flow JSON definition. The file must be attached as multipart/form-data.

        Returns validation errors in the Flow JSON, if any.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: uploadFlowAssets
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              required:
                - file
                - name
                - asset_type
              properties:
                file:
                  type: string
                  format: binary
                  description: Flow JSON file (max 10 MB)
                name:
                  type: string
                  description: Asset name (must be "flow.json")
                  example: flow.json
                asset_type:
                  type: string
                  description: Asset type (must be "FLOW_JSON")
                  example: FLOW_JSON
      responses:
        "200":
          description: Flow assets uploaded successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  validation_errors:
                    type: array
                    items:
                      type: object
                      properties:
                        error:
                          type: string
                          example: INVALID_PROPERTY
                        error_type:
                          type: string
                          example: JSON_SCHEMA_ERROR
                        message:
                          type: string
                        line_start:
                          type: integer
                        line_end:
                          type: integer
                        column_start:
                          type: integer
                        column_end:
                          type: integer
              example:
                success: true
                validation_errors: []
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{flow_id}:
    parameters:
      - name: flow_id
        in: path
        required: true
        description: Flow ID
        schema:
          type: string
    get:
      tags:
        - Flows
      summary: Get flow details
      description: |
        Retrieve detailed information about a specific flow.

        By default returns: id, name, status, categories, validation_errors.

        Use `fields` parameter to request additional information like preview URLs, health status, metrics, etc.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: getFlow
      parameters:
        - name: fields
          in: query
          required: false
          description: |
            Comma-separated list of fields to retrieve.

            Available fields: id, name, status, categories, validation_errors, json_version, data_api_version, endpoint_uri, preview, whatsapp_business_account, application, health_status

            Preview can be invalidated: `preview.invalidate(true)`

            Metrics: `metric.name(ENDPOINT_REQUEST_COUNT).granularity(DAY).since(2024-01-28).until(2024-01-30)`
          schema:
            type: string
          example: id,name,categories,preview,status,validation_errors
        - name: phone_number_id
          in: query
          required: false
          description: Required when accessing flow by ID (unless business_account_id provided)
          schema:
            type: string
        - name: business_account_id
          in: query
          required: false
          description: Required when accessing flow by ID (unless phone_number_id provided)
          schema:
            type: string
      responses:
        "200":
          description: Flow details retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  name:
                    type: string
                  status:
                    type: string
                    enum:
                      - DRAFT
                      - PUBLISHED
                      - DEPRECATED
                      - BLOCKED
                      - THROTTLED
                  categories:
                    type: array
                    items:
                      type: string
                  validation_errors:
                    type: array
                    items:
                      type: object
                  json_version:
                    type: string
                  data_api_version:
                    type: string
                  endpoint_uri:
                    type: string
                    format: uri
                  preview:
                    type: object
                    properties:
                      preview_url:
                        type: string
                        format: uri
                      expires_at:
                        type: string
                        format: date-time
                  health_status:
                    type: object
                    description: Health status of flow and related entities
              example:
                id: flow-1
                name: appointment_booking
                status: DRAFT
                categories:
                  - APPOINTMENT_BOOKING
                validation_errors: []
                json_version: "3.0"
                data_api_version: "3.0"
                endpoint_uri: https://example.com
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Flows
      summary: Update flow metadata
      description: |
        Update flow name, categories, endpoint_uri, or application_id.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: updateFlowMetadata
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: Flow name
                categories:
                  type: array
                  items:
                    type: string
                    enum:
                      - SIGN_UP
                      - SIGN_IN
                      - APPOINTMENT_BOOKING
                      - LEAD_GENERATION
                      - CONTACT_US
                      - CUSTOMER_SUPPORT
                      - SURVEY
                      - OTHER
                  description: Flow categories (at least one required if provided)
                endpoint_uri:
                  type: string
                  format: uri
                  description: URL of the WhatsApp Flow Endpoint (for Flow JSON 3.0+)
                application_id:
                  type: string
                  description: ID of the Meta application connected to the Flow
            example:
              name: Updated Flow Name
              categories:
                - APPOINTMENT_BOOKING
                - CUSTOMER_SUPPORT
      responses:
        "200":
          description: Flow metadata updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
              example:
                success: true
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /flows/{flow_id}:
    parameters:
      - name: flow_id
        in: path
        required: true
        description: Flow ID
        schema:
          type: string
    delete:
      tags:
        - Flows
      summary: Delete flow
      description: |
        Delete a draft flow. This action is not reversible.

        **Only DRAFT flows can be deleted.** Published flows cannot be deleted but can be deprecated.

        **Proxy endpoint**: Proxies directly to Meta Graph API.

        **Note**: This endpoint uses the `/flows/` prefix. It is an alias provided for better developer experience.
      operationId: deleteFlow
      responses:
        "200":
          description: Flow deleted successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
              example:
                success: true
        "400":
          description: Bad request (e.g., trying to delete non-draft flow)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{flow_id}/publish:
    parameters:
      - name: flow_id
        in: path
        required: true
        description: Flow ID
        schema:
          type: string
    post:
      tags:
        - Flows
      summary: Publish flow
      description: |
        Publish a flow. This action is not reversible.

        Once published, the flow and its assets become immutable.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: publishFlow
      responses:
        "200":
          description: Flow published successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{flow_id}/deprecate:
    parameters:
      - name: flow_id
        in: path
        required: true
        description: Flow ID
        schema:
          type: string
    post:
      tags:
        - Flows
      summary: Deprecate flow
      description: |
        Deprecate a published flow.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: deprecateFlow
      responses:
        "200":
          description: Flow deprecated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{business_account_id}/phone_numbers:
    parameters:
      - name: business_account_id
        in: path
        required: true
        description: WhatsApp Business Account ID
        schema:
          type: string
    get:
      tags:
        - Phone Numbers
      summary: List phone numbers
      description: |
        List all phone numbers associated with a business account.

        Returns basic phone number information including verification status and quality rating.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: listPhoneNumbers
      parameters:
        - name: fields
          in: query
          required: false
          description: |
            Comma-separated list of fields to retrieve.

            Available fields: id, verified_name, display_phone_number, quality_rating, code_verification_status, is_official_business_account, name_status, new_name_status, platform_type, throughput, account_mode, certificate, messaging_limit_tier
          schema:
            type: string
          example: id,verified_name,display_phone_number,quality_rating
      responses:
        "200":
          description: Phone numbers retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                          description: Phone number ID
                        verified_name:
                          type: string
                          description: Verified business name associated with the phone number
                        display_phone_number:
                          type: string
                          description: Phone number in international format
                        quality_rating:
                          type: string
                          enum:
                            - GREEN
                            - YELLOW
                            - RED
                            - NA
                            - UNKNOWN
                          description: |
                            Quality rating based on message delivery.
                            - GREEN: High quality
                            - YELLOW: Medium quality
                            - RED: Low quality
                            - NA: Not yet determined
                            - UNKNOWN: Status unknown
                        code_verification_status:
                          type: string
                          description: Verification status of the phone number
                        is_official_business_account:
                          type: boolean
                          description: Whether this is an official business account
                        name_status:
                          type: string
                          description: Status of the business name
                        new_name_status:
                          type: string
                          description: Status of pending name change
                        platform_type:
                          type: string
                          description: Platform type (CLOUD_API, etc.)
                        throughput:
                          type: object
                          description: Messaging throughput limits
                        account_mode:
                          type: string
                          enum:
                            - SANDBOX
                            - LIVE
                          description: Account mode
                        certificate:
                          type: string
                          description: Certificate status
                        messaging_limit_tier:
                          type: string
                          description: Current messaging limit tier
                  paging:
                    $ref: "#/components/schemas/Paging"
              example:
                data:
                  - id: "1906385232743451"
                    verified_name: Jasper's Market
                    display_phone_number: +1 631-555-5555
                    quality_rating: GREEN
                  - id: "1913623884432103"
                    verified_name: Jasper's Ice Cream
                    display_phone_number: +1 631-555-5556
                    quality_rating: NA
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
  /{phone_number_id}:
    parameters:
      - name: phone_number_id
        in: path
        required: true
        description: WhatsApp Business Phone Number ID
        schema:
          type: string
    get:
      tags:
        - Phone Numbers
      summary: Get phone number details
      description: |
        Retrieve detailed information about a specific phone number.

        By default returns basic information. Use `fields` parameter to request additional data like throughput limits, account mode, certificate status, etc.

        **Proxy endpoint**: Proxies directly to Meta Graph API.
      operationId: getPhoneNumber
      parameters:
        - name: fields
          in: query
          required: false
          description: |
            Comma-separated list of fields to retrieve.

            Available fields: id, verified_name, display_phone_number, quality_rating, code_verification_status, is_official_business_account, name_status, new_name_status, platform_type, throughput, account_mode, certificate, messaging_limit_tier

            Example: `fields=id,verified_name,display_phone_number,quality_rating,throughput,messaging_limit_tier`
          schema:
            type: string
          example: id,verified_name,display_phone_number,quality_rating
      responses:
        "200":
          description: Phone number details retrieved successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: Phone number ID
                  verified_name:
                    type: string
                    description: Verified business name associated with the phone number
                  display_phone_number:
                    type: string
                    description: Phone number in international format
                  quality_rating:
                    type: string
                    enum:
                      - GREEN
                      - YELLOW
                      - RED
                      - NA
                      - UNKNOWN
                    description: |
                      Quality rating based on message delivery.
                      - GREEN: High quality
                      - YELLOW: Medium quality
                      - RED: Low quality
                      - NA: Not yet determined
                      - UNKNOWN: Status unknown
                  code_verification_status:
                    type: string
                    description: Verification status of the phone number
                  is_official_business_account:
                    type: boolean
                    description: Whether this is an official business account
                  name_status:
                    type: string
                    description: Status of the business name
                  new_name_status:
                    type: string
                    description: Status of pending name change
                  platform_type:
                    type: string
                    description: Platform type (CLOUD_API, etc.)
                  throughput:
                    type: object
                    description: Messaging throughput limits
                    properties:
                      level:
                        type: string
                        description: Current throughput level
                  account_mode:
                    type: string
                    enum:
                      - SANDBOX
                      - LIVE
                    description: Account mode (SANDBOX for testing, LIVE for production)
                  certificate:
                    type: string
                    description: Certificate status
                  messaging_limit_tier:
                    type: string
                    description: Current messaging limit tier (TIER_50, TIER_250, TIER_1K, TIER_10K, TIER_100K, TIER_UNLIMITED)
              example:
                id: "1906385232743451"
                verified_name: Jasper's Market
                display_phone_number: +1 631-555-5555
                quality_rating: GREEN
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
    post:
      tags:
        - Phone Numbers
      summary: Update phone number settings
      description: |
        Update phone number settings. Common use case is updating the two-step verification PIN.

        **Proxy endpoint**: Proxies directly to Meta Graph API.

        **Note**: Two-step verification is required for WhatsApp Business API. The PIN must be 6 digits.
      operationId: updatePhoneNumber
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                pin:
                  type: string
                  pattern: ^\d{6}$
                  description: 6-digit PIN for two-step verification
                  example: "123456"
              example:
                pin: "123456"
      responses:
        "200":
          description: Phone number settings updated successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
              example:
                success: true
        "400":
          description: Bad request (e.g., invalid PIN format)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
