Skip to main content

Send Messages Guide

This guide shows how to send WhatsApp messages via the Pilot Status API. All sends go through a single endpoint:
Authentication uses the x-api-key: ps_... header (or x-api-key-id) with a number-scoped key — see API Authentication. There is no Bearer-token auth.
Sending from the dashboard Message page

You can also send from the dashboard Message page — it calls the same POST /v1/messages/send endpoint and shows a copy-ready curl.

The endpoint has three mutually exclusive modes: template send (templateId), free-form text (text), and direct media (media + mediaType). Full reference: POST /v1/messages/send.

Prerequisites

  1. A connected WhatsApp number (dashboard /numbers).
  2. An API key for that number (dashboard /api-keys).
  3. For template sends: a template created in /templates (Meta numbers require Meta approval).

1. Send a template message

The most reliable mode — works at any time, including outside the 24h window on Meta numbers.

2. Send free-form text

Send plain text with the text field (no templateId).
On Meta numbers, free-form messages only work within the WhatsApp 24h conversation window (i.e. after the recipient messaged you in the last 24 hours). Outside the window, the send fails asynchronously with META_OUTSIDE_24H_WINDOW in the message.failed webhook — use an approved template instead. Check whether the window is open before sending with GET /v1/service-window.
You can add up to 3 buttons (and, with buttons, a header/footer) to free-form messages — see the send reference.

3. Send direct media

Send an image, video, document, or audio on its own — provide media + mediaType, with no templateId and no text. An optional caption is allowed for image/video/document (not audio). mediaType: "audio" is delivered as a WhatsApp voice note (PTT).
Base64 data URIs are accepted on Meta Cloud API numbers; unofficial (Pilot Status web) numbers require a public http(s) URL.

4. Track delivery

The 202 response returns an id. Persist it and:
  • Poll GET /v1/messages/{id} for QUEUEDSENTDELIVEREDREAD (or FAILED / CANCELED), or
  • Consume webhooks — the response id matches the id field in the message.sent, message.delivered, message.read, and message.failed events.

Next steps