Send messages

Send SMS and WhatsApp messages, one to each person, up to 100 at a time.

Send one message to each person, by SMS or WhatsApp, now or at a time you choose. Send up to 100 in one request: they're queued all or none.

Requirements

  • An API key with the messages.send permission.
  • For SMS, enough SMS on your account. For WhatsApp, your number connected.

Requests

POST /v1/messages

Request syntax

{
  "messages": [
    {
      "to": "<PHONE_NUMBER>",
      "customerId": "<CUSTOMER_ID>",
      "channel": "<CHANNEL>",
      "from": "<SENDER>",
      "content": { "text": "<TEXT>" },
      "template": "<TEMPLATE_NAME>",
      "variables": { "<KEY>": "<VALUE>" },
      "sendAt": "<TIME>",
      "replyTo": "<RECEIVED_MESSAGE_ID>"
    }
  ]
}
PlaceholderDescriptionSample value
<PHONE_NUMBER>String. Who it's to, with the country code. Use to or customerId, not both.+255712345678
<CUSTOMER_ID>String. One of your customers. Their phone is used.cus_4hq2v9n1c8x0t6pk
<CHANNEL>String. sms or whatsapp. Optional with a template, which has its own.sms
<SENDER>String. Optional. An SMS sender ID from GET /v1/messaging/senders. Left out, yours or the shared one.DUKA AMINA
<TEXT>String. What it says. SMS: up to 6 parts. WhatsApp: up to 4,096 characters. Leave out with a template.Your order is ready.
<TEMPLATE_NAME>String. A saved template's name or id. See Send templates.auth_1
<KEY>, <VALUE>Object of strings. The template's {{data.x}} and {{secret.x}} values.{ "code": "482913" }
<TIME>String. Optional. When to send it, within a year. Left out, now. WhatsApp text always goes now.2026-11-13T07:00:00Z
<RECEIVED_MESSAGE_ID>String. Optional. WhatsApp only: a message the customer sent, which this reply quotes.rcv_8f2k1m0p9x3a7q2z

Example request

curl https://api.goomzo.africa/v1/messages \
  -H "Authorization: Bearer $GOOMZO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-ready" \
  -d '{
    "messages": [
      { "to": "+255712345678", "channel": "sms", "content": { "text": "Amina, order #1042 is ready." } }
    ]
  }'

Responses

The answer is 201 with the messages, in the order you sent them.

{
  "items": [
    {
      "id": "msg_7c1x9v2b4n6m8q0w",
      "customerId": "cus_4hq2v9n1c8x0t6pk",
      "to": { "name": "Amina", "phone": "+255712345678" },
      "channel": "sms",
      "content": { "text": "Amina, order #1042 is ready." },
      "status": "sending",
      "error": null,
      "sendAt": "2026-11-12T09:14:03Z",
      "private": false,
      "template": null
    }
  ]
}
PlaceholderDescriptionSample value
idString. The message's id. Webhooks and GET /v1/messages/{id} use it.msg_7c1x9v2b4n6m8q0w
statusString. Where it is. See statuses.sending
privateBoolean. It was sent with secrets, shown as •••••• in content.false
templateObject or null. The WhatsApp template it went as.null

Important: This answer only means Goomzo accepted the message. It doesn't mean it was delivered. Follow its status with webhooks.

Notes

  • All or none: every message is checked, and the SMS for all of them set aside together. If one isn't valid, or there isn't enough SMS for all of them, none is sent, and the error names the bad one, such as messages[1].to.
  • Not enough SMS: 422 insufficient_sms says how many the request needed and how many were available.
  • Unknown numbers: a number that isn't one of your customers is still sent to, under the number itself. No customer is added.
  • Before you send: POST /v1/messaging/estimate takes the same channel, content and audience, and says what it would use.

Next steps

Last updated