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

# Send Message

> This endpoint is used to send a message to a chat




## OpenAPI

````yaml POST /message/send
openapi: 3.0.3
info:
  title: API - Local
  description: >-
    #### Welcome to the official Postman collection of Periskope API


    Periskope APIs enable you automate actions on your WhatsApp phone, and the
    Periskope platform


    - Read more about the APIs & webhooks here -
    [https://docs.periskope.app/api-reference/introduction](https://docs.periskope.app/api-reference/introduction)
        
    - We encourage responsible usage of the APIs. Follow these best practices
    and recommendations for safe actions on WhatsApp -
    [https://docs.periskope.app/get-started/best-practices](https://docs.periskope.app/get-started/best-practices)
        

    #### Getting Started


    ##### Pre-requisites:


    1. **Sign up for a free account on Periskope:** To use the Periskope API,
    you need to have an active Periskope account. If you don’t have one, you can
    sign up for a 7-day free trial [here](https://console.periskope.app).
        
    2. **Scan the QR code from WhatsApp to connect your phone:** A connected
    phone is required to use the APIs
        
    3. **Go to** [Settings &gt;
    API](https://console.periskope.app/settings/api), and generate an API key
    for your organization - The API key is used to authenticate every request.
    Please keep this secure
        

    ##### Using Postman:


    1. **Fork the collection so you can edit values and test the APIs in your
    own postman environment:** To fork the collection, click on the three dots
    next to v1. Then click on create a fork (_shortcut: Ctrl + Alt + F)._
        
    2. **Update the value of the variables in the collection:**  
        \- Update the API key with the key generated in Step 3  
        \- Update the phone number with your connected number. This number will be added to the `x-phone` header across requests
        
        It must be in the format of country code+number, with no special characters or spaces _e.g. +91 98745 32456 becomes 919874532456_
        

    For any help or feedback, please contact us at
    [support@periskope.app](https://mailto:support@periskope.app), or ping us on
    [WhatsApp](https://what.sapp.link/periskope)
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.periskope.app/v1
security:
  - bearerAuth: []
tags:
  - name: contacts
  - name: tickets
  - name: tasks
  - name: phones
  - name: message
  - name: queue
  - name: chats
  - name: group
  - name: members
  - name: webhooks
paths:
  /message/send:
    post:
      tags:
        - message
      summary: Send Message
      description: |
        This endpoint is used to send a message to a chat
      operationId: sendMessage
      parameters:
        - name: x-phone
          in: header
          schema:
            type: string
            example: '{{orgPhone}}'
          description: >-
            Please provide the number of the phone you want to call with this
            API in the header. The number must be in country code + number
            format without any characters or spaces, e.g. 919876543210;
            Alternatively, provide the phone_id (phone-xxxxxxxxxxxx) in the
            header
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - chat_id
              properties:
                chat_id:
                  type: string
                  example: 919537851844@c.us
                  description: >-
                    - For groups, enter the chat_id of the group. This will be a
                    string that ends with @g.us

                    - For 1-1 chats, enter the country_code + number of the
                    recipient e.g.
                    [919537851844@c.us](https://mailto:919537851844@c.us) (The
                    @c.us is optional)
                message:
                  type: string
                  description: >-
                    The text body or caption. You can use basic markdown
                    formatting supported by WhatsApp e.g. * for bold, and _ for
                    italic, etc.
                media:
                  type: object
                  properties:
                    type:
                      type: string
                      enum:
                        - document
                        - image
                        - video
                        - audio
                      description: The type of media being sent
                    url:
                      type: string
                      description: Public URL that hosts the content to be sent
                    filedata:
                      type: string
                      description: Raw bytes of the file, represented in base64
                    filename:
                      type: string
                      description: The filename of the media
                    mimetype:
                      type: string
                      description: The MIME type of the media file
                  required:
                    - type
                    - filename
                    - mimetype
                  description: |-
                    Media object containing file information and content

                    Note: You must specify either `filedata` or `url`
                poll:
                  type: object
                  description: |
                    - `pollName` - The question or title of the poll
                      - `pollOptions` - Raw bytes of the file, represented in base64
                      - `options` - Additional options to be sent with the poll
                        - `allowMultipleAnswers` - Boolean. When set to true, respondents can select multiple options
                        - `pollId` - Optional unique identifier of the poll. Useful when sending it across multiple chats
                reply_to:
                  type: string
                  description: To reply to a message, add the message_id in this field
                options:
                  type: object
                  description: >-
                    - `hide_url_preview` - Set it to true to disable automatic
                    link previews in the messages containing URLs
            examples:
              Send Message:
                value:
                  chat_id: 919537851844@c.us
                  message: Hello World
      responses:
        '200':
          description: Text Message / Media Message / Reply Message / Poll Message
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
                example: '*'
            Connection:
              schema:
                type: string
                example: keep-alive
            Content-Length:
              schema:
                type: string
                example: '70'
            Date:
              schema:
                type: string
                example: Wed, 22 Jan 2025 10:07:53 GMT
            ETag:
              schema:
                type: string
                example: W/"46-G83wmhGAIRrmKrMUWfoeGk61n3A"
            Keep-Alive:
              schema:
                type: string
                example: timeout=5
            X-Powered-By:
              schema:
                type: string
                example: Express
            X-RateLimit-Limit:
              schema:
                type: string
                example: '10'
            X-RateLimit-Remaining:
              schema:
                type: string
                example: '9'
            X-RateLimit-Reset:
              schema:
                type: string
                example: '1737540475'
            x-periskope-org-id:
              schema:
                type: string
                example: 2997dd64-89bf-48d3-9a22-b314fca017e5
            x-periskope-phone-id:
              schema:
                type: string
                example: phone-bqzvyibhmwkaergr
            x-periskope-trace-id:
              schema:
                type: string
                example: bec43610-d8a8-11ef-8033-3b03afb6e098
          content:
            application/json:
              schema:
                type: object
                description: >-
                  The response object confirms that your message request has
                  been accepted and added to the processing queue for
                  asynchronous delivery.


                  **What you receive:**

                  - `queue_id` — A unique identifier for your enqueued message
                  task. Save this value to track your message's progress,
                  correlate it with webhook events, or reference it in support
                  requests.

                  - `queue_position` — Your message's position in the processing
                  queue at the moment it was enqueued. This is zero-based (0 =
                  first in queue, 1 = second, etc.). Note that this position
                  reflects the queue state at enqueue time and may change as
                  other messages are processed.

                  - `status` — The initial status of the message, always
                  `queued` at this point.

                  - `unique_id` — A provisional identifier (when available) that
                  helps correlate the queued request with downstream message
                  objects or WhatsApp provider references.

                  - `track_by` — A convenience object with ready-to-use tracking
                  URLs. Use `track_by.unique_id` to poll delivery status via
                  `GET /message/{unique_id}/status`, or `track_by.queue_id` to
                  look up the job via the queue API.


                  **Understanding the queue system:**

                  - Messages are NOT sent immediately upon receiving this
                  response. Instead, they are queued and processed
                  asynchronously in the background.

                  - Processing typically begins within seconds, but actual
                  timing depends on:
                    - Current queue depth and system throughput
                    - Message type and size (text messages are faster than media)
                    - Media file size and processing requirements
                    - Rate limits applied to your phone number or organization
                    - WhatsApp provider connectivity and response times
                  - The system automatically retries failed messages for
                  transient errors (network issues, temporary provider
                  unavailability, etc.). Messages will be retried up to **3
                  times** with exponential backoff delays between attempts.
                  After 3 failed attempts, the message will be marked as failed
                  and no further retries will occur.


                  **How the queue_id maps to your message:**

                  - When you receive the `queue_id`, your message is in a
                  "queued" state

                  - Once processing begins, the `queue_id` becomes associated
                  with a provisional `sent_message_id` in the message object

                  - After successful delivery to WhatsApp, the `queue_id` maps
                  to the final provider message ID

                  - You can use the `queue_id` to track the message through its
                  entire lifecycle: queued → processing → sent → delivered →
                  read (or failed)


                  **Tracking your message status:**

                  You have two primary methods to monitor your message:


                  1. **Message Status API** — Use `GET
                  /message/{unique_id}/status` to check the delivery status of
                  your message. The `unique_id` is returned in this response.
                  The status field can be one of:
                     - `queued` — Waiting to be processed
                     - `sending` — Currently being sent to WhatsApp
                     - `sent` — Successfully sent to WhatsApp servers
                     - `delivered` — Delivered to the recipient's device
                     - `read` — Read by the recipient
                     - `failed` — Delivery failed after all retry attempts (check `status_description` for reason)

                  2. **Webhook notifications** — If you have webhooks
                  configured, you'll automatically receive real-time events as
                  your message progresses:
                     - `message.sent` — Fired when the message is successfully sent to WhatsApp
                     - `message.delivered` — Fired when the message is delivered to the recipient
                     - `message.read` — Fired when the message is read (requires read receipts to be enabled)
                     - `message.failed` — Fired if the message fails to send or deliver after all retry attempts
                     - Each webhook event includes the `queue_id` so you can correlate it with your original request

                  **Error handling and retries:**

                  - If a message fails due to transient errors (network issues,
                  temporary provider unavailability, timeouts), the system will
                  automatically retry the message

                  - Messages are retried up to **3 times** with exponential
                  backoff delays (the delay increases with each retry attempt)

                  - Permanent failures (invalid chat_id, blocked numbers, etc.)
                  will not be retried

                  - After 3 failed retry attempts, the message status will be
                  set to `failed` and you'll receive a `message.failed` webhook
                  event if configured


                  **Best practices:**

                  - Always save the `queue_id` immediately after receiving the
                  response

                  - Don't poll the queue status too frequently (recommended:
                  every 1-2 seconds for active monitoring, or use webhooks for
                  real-time updates)

                  - Implement proper error handling for failed messages

                  - Use webhooks when possible for more efficient, event-driven
                  tracking

                  - Monitor your message status and handle failed messages
                  appropriately in your application


                  **Related documentation:**

                  - [Message Status API](/api-reference/message/message-status)
                  — Track delivery status by unique_id

                  - [List Queue Jobs
                  API](/api-reference/message/list-queue-jobs) — Query job
                  status by queue_id or broadcast_id

                  - [Queue Health API](/api-reference/message/queue-health) —
                  Check the overall status of the message queue

                  - [Webhooks Documentation](/api-reference/webhooks) — Guide to
                  setting up and handling webhook events
              examples:
                Media Message:
                  value:
                    status: queued
                    unique_id: 3EB0630434929F6B94327F
                    queue_id: b986ccf5-7698-49ae-bd49-3125e2b06697
                    queue_position: 0
                    track_by:
                      unique_id: GET /messages/3EB0630434929F6B94327F/status
                Reply Message:
                  value:
                    status: queued
                    unique_id: 3EB0630434929F6B94327F
                    queue_id: b986ccf5-7698-49ae-bd49-3125e2b06697
                    queue_position: 0
                    track_by:
                      unique_id: GET /messages/3EB0630434929F6B94327F/status
                Text Message:
                  value:
                    status: queued
                    unique_id: 3EB0630434929F6B94327F
                    queue_id: b986ccf5-7698-49ae-bd49-3125e2b06697
                    queue_position: 0
                    track_by:
                      unique_id: GET /messages/3EB0630434929F6B94327F/status
      x-codeSamples:
        - lang: TypeScript
          label: Node.js
          source: |-
            import { PeriskopeApi } from '@periskope/periskope-client';

            const client = new PeriskopeApi({
              authToken: 'YOUR_API_KEY',
              phone: 'YOUR_PHONE_NUMBER', // e.g., '919876543210'
            });

            async function sendMessage() {
              const response = await client.message.send({
                chat_id: '919537851844',
                message: 'Hi from Periskope'
              });

              console.log(response);
            }

            sendMessage();
        - lang: cURL
          label: cURL
          source: |-
            curl -X POST \
              https://api.periskope.app/v1/message/send \
              -H 'Authorization: Bearer <token>' \
              -H 'Content-Type: application/json' \
              -H 'x-phone: YOUR_PHONE_NUMBER' \
              -d '{
                "chat_id": "919537851844@c.us",
                "message": "Hi from Periskope"
              }'
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````