Save 44% with yearly billing, 5 months free.View Plans
textbee Logotextbee.dev
Documentation

Sending bulk SMS

Send many SMS in one call with POST /gateway/send-bulk-sms or a CSV upload, pace the phone with Send Delay and track failed recipients.

Updated

You can send many messages at once in two ways: call POST /gateway/send-bulk-sms from your code, or upload a CSV file in the dashboard. Both create one batch with one message per recipient. The phone then sends the batch at the pace of its Send Delay setting.

Option 1: The API

POST/api/v1/gateway/send-bulk-sms, open in the API reference

Use this endpoint when each group of recipients needs a different text. For the same text to every recipient, POST /gateway/send-sms with a recipients array is enough.

Request fields

FieldTypeRequiredDescription
messagesobject[]YesThe messages to send. Each item is described below.
deviceIdstringNoThe phone that sends the whole batch. Without it, textbee uses your default device, or else the enabled device with the most recent heartbeat.
messageTemplatestringNoA label for the batch. It is not sent to anyone.

Each item in messages has these fields:

FieldTypeRequiredDescription
messagestringYesThe text for this item.
recipientsstring[]YesPhone numbers in E.164 format that get this text.
simSubscriptionIdnumberNoThe SIM for this item. The ID can change after a SIM swap, so copy the current one from the textbee app. See Send from a specific SIM.
scheduledAtstringNoAn ISO 8601 time with a timezone for this item. See Schedule a message.

Example

This request sends a personal reminder to two people and a general notice to a third, all from one phone:

Shell
curl -X POST https://api.textbee.dev/api/v1/gateway/send-bulk-sms \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "deviceId": "664a9b8cd0e1f2a3b4c5d6e7",
    "messageTemplate": "September reminders",
    "messages": [
      { "recipients": ["+12015550123"], "message": "Hi Ana, your appointment is on Tuesday at 10am." },
      { "recipients": ["+12015550124"], "message": "Hi Ben, your appointment is on Wednesday at 2pm." },
      { "recipients": ["+12015550125"], "message": "The office is closed on Friday." }
    ]
  }'

Response

A successful call returns 200 with one smsBatchId for the whole batch:

JSON
{
  "data": {
    "success": true,
    "message": "Bulk SMS added to queue for processing",
    "smsBatchId": "66b1f2c3a4d5e6f7a8b9c0d2",
    "recipientCount": 3
  }
}

A large batch also returns estimatedCompletionAt: the time the phone should finish, based on its Send Delay. The status codes are the same as for POST /gateway/send-sms.

Option 2: CSV upload in the dashboard

Use the CSV upload to send a personalized message to each row of a spreadsheet without code.

  1. Open the dashboard and go to Messaging > Bulk Send.
  2. Upload your CSV. The file needs a header row and one row per recipient. It can have any other columns you want to use in the message. The maximum file size is 1 MB.
  3. Choose the phone column and device. The dashboard guesses the phone column from your headers. Check it, then pick the device under Send from and, if you want, a SIM.
  4. Write your message. Insert a column with {{ columnName }}. Each recipient gets the values from their own row.
  5. Review and send. Step through the preview for each recipient. Nothing is sent until you confirm.

Example CSV:

phone,name,orderId
+12015550123,Ana,1001
+12015550124,Ben,1002

Example template: Hello {{ name }}, your order #{{ orderId }} is ready!

The dashboard skips rows with an empty, invalid or duplicate phone number and tells you which ones.

Pace the phone with Send Delay

The phone does not send a whole batch at once. It waits a fixed gap between messages. You set the gap in the app: Settings > Send Delay, from 0 to 3600 seconds. The default is 5 seconds. The API shows the value as smsSendDelaySeconds on the device.

Carriers watch for phones that send many messages in a short time. A fast burst can get the SIM blocked or its messages filtered, and Android itself can refuse to send more. A longer delay protects the SIM but makes a large batch take longer. When the delay is 0, the app's Device health screen warns: "No gap between messages. Carriers may block a phone that sends too fast."

textbee releases large batches in waves that match the delay, so the phone is never asked to hold more than it can send. For very large sends, split the work across several phones with deviceId.

Follow the batch

The batch endpoint returns the batch totals and every message in it:

Shell
curl https://api.textbee.dev/api/v1/gateway/devices/664a9b8cd0e1f2a3b4c5d6e7/sms-batch/66b1f2c3a4d5e6f7a8b9c0d2 \
  -H "x-api-key: YOUR_API_KEY"

The batch object has a status of pending, processing, completed, partial_success, failed or unknown, calculated from its messages. It also counts the messages in each state: successCount (sent or delivered), failureCount, pendingCount, dispatchedCount, sentCount, deliveredCount and unknownCount. Batch status explains each value. The messages array has one message per recipient with its own status.

To list only the recipients that failed, filter the message history by batch and status:

Shell
curl "https://api.textbee.dev/api/v1/gateway/messages?smsBatchId=66b1f2c3a4d5e6f7a8b9c0d2&status=failed" \
  -H "x-api-key: YOUR_API_KEY"

Each failed message has an errorCode and an errorMessage. Delivery status and message states explains the codes.

Webhooks for a batch

If you subscribe to MESSAGE_SENT, MESSAGE_DELIVERED or MESSAGE_FAILED, textbee makes one webhook delivery per recipient, not one per batch. A batch of 500 recipients produces up to 500 MESSAGE_SENT deliveries. Each one carries the smsBatchId. Make sure your endpoint can handle that volume. See Webhook events.

Plan limits

Each recipient counts as one message. Your plan's daily, monthly and per-batch limits apply. A batch with more recipients than your per-batch limit returns 429 and sends nothing. The body names the limit. Split the recipients into smaller batches, or upgrade. The pricing page lists the limits.

Frequently asked questions

Can one bulk request use more than one phone?

No. deviceId applies to the whole batch. To send from several phones, make one request per phone.

Can each item have its own schedule?

Yes. Set scheduledAt on each item. Items with the same time go out together.

Why is my batch still processing after an hour?

The phone sends one message per Send Delay gap, so large batches take time. Check estimatedCompletionAt from the response, and check that the phone is online. See Messages not sending.

Does the CSV upload use the API?

Yes. The dashboard creates a batch in the same way. You follow it with the same endpoints and webhooks.

Next steps