TryVox

Send a Message

Send a WhatsApp or SMS message via the Messaging API.

Send a Message

A single endpoint sends every message type — text, media, template, or interactive. The message_type field determines which fields are required.

Endpoint

POST https://api.tryvox.io/v1/messaging/messages

Request body

FieldTypeRequiredDescription
channel_iduuidyesThe channel to send from. See Channels.
tostringyesRecipient phone number, E.164.
message_typestringyestext, image, audio, video, document, template, interactive.
contentstringconditionalMessage text. Required for text. Optional caption for image / video / document.
media_urlstringconditionalPublic URL of the media file. Required for image, audio, video, document.
media_mime_typestringconditionalMIME type of the media (e.g. image/jpeg, application/pdf). Required when media_url is set.
template_namestringconditionalName of the registered template. Required when message_type is template.
template_paramsobjectconditionalTemplate language + components (Meta's shape). Required for template.

First contact with a recipient on WhatsApp must use a template. The 24-hour customer-service window opens after the recipient replies, after which text and media types are allowed.

Examples

Plain text (in 24-hour window)

curl -X POST https://api.tryvox.io/v1/messaging/messages \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
    "to": "+14155551234",
    "message_type": "text",
    "content": "Thanks for getting back to us. How can we help today?"
  }'

Image with caption

curl -X POST https://api.tryvox.io/v1/messaging/messages \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
    "to": "+14155551234",
    "message_type": "image",
    "media_url": "https://your-cdn.example/invoice-april.png",
    "media_mime_type": "image/png",
    "content": "Your April invoice"
  }'

Template (first contact, OTP)

curl -X POST https://api.tryvox.io/v1/messaging/messages \
  -u $TRYVOX_AUTH_ID:$TRYVOX_AUTH_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "channel_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
    "to": "+14155551234",
    "message_type": "template",
    "template_name": "login_otp",
    "template_params": {
      "language": "en_US",
      "components": [
        {
          "type": "body",
          "parameters": [{"type": "text", "text": "284731"}]
        }
      ]
    }
  }'

The template_params object is passed through to the Meta WhatsApp Cloud API verbatim — see Meta's template reference for component structure.

Response

201 Created:

{
  "id": "1b2c3d4e-5f60-7180-9a2b-3c4d5e6f7a8b",
  "channel_id": "8f7a4b2e-91c2-4f3d-9a1e-2c4b6d8f0a1c",
  "conversation_id": "3c4d5e6f-7a8b-9c0d-1e2f-3a4b5c6d7e8f",
  "direction": "outbound",
  "to": "+14155551234",
  "message_type": "text",
  "content": "Thanks for getting back to us. How can we help today?",
  "status": "queued",
  "created_at": "2026-04-09T10:30:00Z"
}

The send is queued — the response returns before delivery confirmation. Track lifecycle via webhook events on the channel:

  • message.sent — accepted by Meta
  • message.delivered — handset received
  • message.read — recipient opened (only if read receipts are enabled)
  • message.failed — delivery failed

Subscribe in Notifications → Webhooks.

Errors

StatusCodeReason
400VALIDATION_FAILEDMissing required field for the chosen message_type, or to not E.164
401INVALID_CREDENTIALSAuth ID / Auth Token bad
403CHANNEL_INACTIVEThe channel is disabled or its Meta access token is rejected
403OUTSIDE_CS_WINDOWTried text/media to a recipient who hasn't replied within 24h. Use template.
403DLT_NOT_REGISTEREDSMS to +91 and no matching DLT template (see DLT)
404CHANNEL_NOT_FOUNDchannel_id doesn't belong to this tenant
404TEMPLATE_NOT_FOUNDtemplate_name not registered on this channel — sync via Templates
429RATE_LIMITEDPer-channel send rate exceeded — retry with the Retry-After header

Notes

  • One conversation per (channel, recipient) pair. The first message creates the conversation; subsequent sends reuse conversation_id.
  • Idempotency is not exposed yet. Retrying the same payload duplicates the message. Coalesce on your side or wait for the lifecycle webhook before retrying.
  • Media URLs must be reachable from Meta's infrastructure, not just from TryVox. Public S3 buckets / CDNs are fine; localhost tunnels often aren't.
  • Outbound SMS uses the same endpoint with a text message type and a channel whose underlying carrier is SMS-capable. The DLT validator runs for +91 destinations only.

On this page