> ## Documentation Index
> Fetch the complete documentation index at: https://docs.watx.in/llms.txt
> Use this file to discover all available pages before exploring further.

# Send a message

> Sends a WhatsApp message to a phone number. You pass a number, not an
internal id: the endpoint finds or creates the contact and the WhatsApp
conversation, then sends.

A free-form message (text or media) only reaches a customer inside the
24-hour customer service window. Outside it, send `type: "template"`
with an approved template.

Requires the `messages:send` scope.




## OpenAPI

````yaml /openapi.yaml post /messages
openapi: 3.1.0
info:
  title: Watx API
  version: '1'
  description: |
    The Watx public REST API. Send WhatsApp messages, manage contacts and
    segments, read conversations and messages, launch broadcasts, and register
    webhook endpoints.

    Every request authenticates with a workspace API key sent as a bearer
    token. A key acts on exactly one workspace and can only do what its scopes
    allow. Each operation below names the scope it requires.
  contact:
    name: Watx support
    email: support@watx.in
servers:
  - url: https://api.watx.in/v1
    description: Production
security:
  - apiKey: []
tags:
  - name: Account
    description: Check which workspace a key belongs to and what it can do.
  - name: Messages
    description: Send a WhatsApp message to a phone number.
  - name: Contacts
    description: Create, read, update and list contacts.
  - name: Conversations
    description: Read conversations and their messages.
  - name: Broadcasts
    description: Launch a template broadcast and follow its progress.
  - name: Segments
    description: Named audiences — static lists and saved filters.
  - name: Webhooks
    description: Register endpoints that receive events from your workspace.
paths:
  /messages:
    post:
      tags:
        - Messages
      summary: Send a message
      description: |
        Sends a WhatsApp message to a phone number. You pass a number, not an
        internal id: the endpoint finds or creates the contact and the WhatsApp
        conversation, then sends.

        A free-form message (text or media) only reaches a customer inside the
        24-hour customer service window. Outside it, send `type: "template"`
        with an approved template.

        Requires the `messages:send` scope.
      operationId: sendMessage
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SendMessageRequest'
            examples:
              text:
                summary: Plain text
                value:
                  to: '+919876543210'
                  type: text
                  text: Your order has been packed.
              template:
                summary: Template with two body values
                value:
                  to: '+919876543210'
                  type: template
                  template:
                    name: order_update
                    language: en_US
                    params:
                      - Priya
                      - A-1042
              media:
                summary: Document with a caption
                value:
                  to: '+919876543210'
                  type: document
                  media_url: https://files.example.com/invoice-1042.pdf
                  filename: invoice-1042.pdf
                  text: Your invoice.
      responses:
        '201':
          description: The message was accepted by WhatsApp and stored.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/SendMessageResult'
              example:
                data:
                  message_id: 9d1f4b2a-6c3e-4a51-bf2d-0a7c9e114b3f
                  whatsapp_message_id: wamid.HBgMOTE5ODc2NTQzMjEwFQIAERgS
                  conversation_id: 3c5b1e77-90aa-4c0e-8f71-1d2a3b4c5d6e
                  contact_id: 7e2d9c01-55b4-4a3d-9c8e-0f1a2b3c4d5e
                  contact_created: false
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          description: |
            WhatsApp rejected the send. `code` is `meta_error` and `message`
            quotes what Meta said.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: meta_error
                  message: >-
                    Meta API error: (#132000) Number of parameters does not
                    match the expected number of params
components:
  schemas:
    SendMessageRequest:
      type: object
      required:
        - to
      properties:
        to:
          type: string
          description: |
            The recipient's phone number in E.164 form, for example
            `+919876543210`. A number without a country code is read using the
            workspace's default country.
          example: '+919876543210'
        type:
          type: string
          enum:
            - text
            - template
            - image
            - video
            - document
            - audio
          default: text
          description: What kind of message to send.
        text:
          type: string
          description: |
            The message body for `type: "text"`, or the caption for an image,
            video or document. A caption is capped at 1024 characters.
        media_url:
          type: string
          format: uri
          description: |
            Public URL of the file. Required for `image`, `video`, `document`
            and `audio`.
        filename:
          type: string
          description: The file name shown in the chat for a document.
        name:
          type: string
          description: |
            A name for the contact. Used when this number is new, and updates
            the name if it differs from the one on file.
        template:
          type: object
          description: 'Required for `type: "template"`.'
          required:
            - name
          properties:
            name:
              type: string
              description: The approved template's name.
            language:
              type: string
              default: en_US
              description: The template's language code.
            params:
              description: |
                Either an array of strings — the body values, in placeholder
                order — or an object for templates that also need a header,
                buttons or carousel cards.
              oneOf:
                - type: array
                  items:
                    type: string
                - $ref: '#/components/schemas/TemplateSendParams'
        reply_to_message_id:
          type: string
          format: uuid
          description: |
            Quote an earlier message. It must belong to the same conversation.
    SendMessageResult:
      type: object
      properties:
        message_id:
          type: string
          format: uuid
          description: The Watx message id.
        whatsapp_message_id:
          type: string
          description: WhatsApp's own message id, which delivery events refer to.
        conversation_id:
          type: string
          format: uuid
        contact_id:
          type: string
          format: uuid
        contact_created:
          type: boolean
          description: True when this call created the contact.
    Error:
      type: object
      description: |
        Every failure uses this shape. Branch on `error.code`, which is stable;
        `error.message` is written for people and may be reworded.
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: |
                One of `bad_request`, `invalid_request`, `unauthorized`,
                `forbidden`, `not_found`, `rate_limited`, `internal`, or a
                domain code such as `whatsapp_not_configured`, `meta_error`,
                `template_malformed`, `plan_limit_reached`,
                `subscription_lapsed`.
              example: bad_request
            message:
              type: string
              example: '''phone'' is required'
    TemplateSendParams:
      type: object
      description: |
        Structured send-time values, for a template that needs more than body
        text. Anything the template does not have is ignored.
      properties:
        body:
          type: array
          description: Body values in placeholder order.
          items:
            type: string
        bodyNamed:
          type: object
          description: |
            Body values keyed by parameter name, for a template that uses named
            parameters. Takes precedence over `body` for a name it carries.
          additionalProperties:
            type: string
        headerText:
          type: string
          description: The value for a text header that carries a variable.
        headerMediaUrl:
          type: string
          description: Public URL for an image, video or document header.
        headerMediaId:
          type: string
          description: A media id already uploaded to WhatsApp, instead of a URL.
        headerFilename:
          type: string
          description: |
            The file name shown in the chat for a document header. Without it
            WhatsApp shows the attachment as "Untitled".
        headerLocation:
          $ref: '#/components/schemas/TemplateLocation'
        buttonParams:
          type: object
          description: |
            Values for dynamic buttons, keyed by button index (`"0"`, `"1"`) —
            the URL suffix for a dynamic URL button, the code for a copy-code
            button.
          additionalProperties:
            type: string
        cards:
          type: array
          description: One entry per card of a carousel template, in card order.
          items:
            $ref: '#/components/schemas/TemplateCardParams'
    TemplateLocation:
      type: object
      description: The map pin for a template with a location header.
      required:
        - latitude
        - longitude
      properties:
        latitude:
          type: string
        longitude:
          type: string
        name:
          type: string
        address:
          type: string
    TemplateCardParams:
      type: object
      description: |
        Send-time values for one card of a carousel template, in card order.
        Keep empty entries in place — position decides which card a value
        belongs to.
      properties:
        headerMediaUrl:
          type: string
          description: Public URL of this card's image or video.
        headerMediaId:
          type: string
          description: A media id already uploaded to WhatsApp.
        body:
          type: array
          items:
            type: string
        bodyNamed:
          type: object
          additionalProperties:
            type: string
        buttonParams:
          type: object
          description: >-
            Values for this card's buttons, keyed by button index (`"0"`,
            `"1"`).
          additionalProperties:
            type: string
  responses:
    BadRequest:
      description: The request was malformed or a value was unusable.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: bad_request
              message: >-
                'to' must be a valid phone number in E.164 format (e.g.
                +14155550123)
    Unauthorized:
      description: |
        The key is missing, malformed, unknown, revoked or expired. All four
        answer the same way.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Missing or invalid API key
    PaymentRequired:
      description: |
        The workspace has used up this plan limit for the month, or its
        subscription has lapsed. Reads keep working; the things that spend do
        not.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Forbidden:
      description: The key is valid but was not granted the scope this operation requires.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: forbidden
              message: This API key is missing the 'messages:send' scope
    RateLimited:
      description: |
        More than 120 requests in a minute for this key. `Retry-After` says how
        many seconds to wait.
      headers:
        Retry-After:
          description: Seconds until the window resets.
          schema:
            type: integer
        X-RateLimit-Limit:
          description: Requests allowed per window.
          schema:
            type: integer
        X-RateLimit-Remaining:
          description: Requests left in this window.
          schema:
            type: integer
        X-RateLimit-Reset:
          description: Unix time in seconds when the window resets.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limited
              message: Rate limit exceeded for this API key
  securitySchemes:
    apiKey:
      type: http
      scheme: bearer
      description: |
        Your workspace API key, created in **Settings → API keys**, sent as
        `Authorization: Bearer <key>`. New keys start with `watx_live_`; keys
        issued before the rename start with `converse360_live_` and still work.

````