Broadcasts
Send a Broadcast
Send one message to a list of phone numbers or email addresses, now or at a set time. The request returns as soon as the list is accepted; delivery drains in the background.
POST
/v1/broadcastParameters
channel"SMS" | "EMAIL"optionalDefaults to "SMS". Upper case here — unlike OTP send, which takes lower case.
messagestringrequiredUp to 160 characters for SMS (one segment — longer messages are rejected, not split), up to 5,000 for email. Leading and trailing whitespace is trimmed.
recipientsstring[]requiredPhone numbers in E.164 for SMS, email addresses for email. At least one, at most 350,000 after cleaning.
scheduledAtISO 8601optionalWhen to start sending. Omit to send immediately.
Bodies up to 5 MB are accepted on this route — roughly 350,000 numbers. Supports the Idempotency-Key header, which you should always send here. Recipient quotas apply on top of request limits — see Sending quotas.
1. SMS, sent now
- Situation: You want to tell your customers about a closure today.
curl -X POST https://api.transmitinfra.com/v1/broadcast \
-H "Authorization: Bearer $TRANSMIT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: closure-notice-2026-09-26" \
-d '{
"message": "Our offices are closed on Monday for Tobaski.",
"recipients": [
"+220833001234",
"+220877005678"
]
}'- Result: The broadcast is created in
PROCESSINGand abroadcast.queuedwebhook fires. Keep theidto track progress.
{
"data": {
"id": "5b1e7c2a-9f04-4c3e-8a61-2d7f0e9b4c18",
"channel": "SMS",
"message": "Our offices are closed on Monday for Tobaski.",
"status": "PROCESSING",
"totalCount": 2,
"acceptedCount": 0,
"deliveredCount": 0,
"failedCount": 0,
"scheduledAt": null,
"createdAt": "2026-09-26T11:41:08.000Z",
"completedAt": null
}
}2. SMS, scheduled
- Situation: You want statements to land at 6 AM on the first of the month.
curl -X POST https://api.transmitinfra.com/v1/broadcast \
-H "Authorization: Bearer $TRANSMIT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: statements-2026-10" \
-d '{
"message": "Your September statement is ready.",
"recipients": [
"+220833001234",
"+220877005678"
],
"scheduledAt": "2026-10-01T06:00:00.000Z"
}'- Result: The list is accepted and counted now; sending starts at
scheduledAt. A time in the past sends immediately. Until it sends, a scheduled broadcast counts toward your in-flight quota.
3. Email
- Situation: You want to reach customers by email instead.
curl -X POST https://api.transmitinfra.com/v1/broadcast \
-H "Authorization: Bearer $TRANSMIT_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: newsletter-2026-09" \
-d '{
"channel": "EMAIL",
"message": "September update\nWe have opened a new branch in Serekunda.",
"recipients": [
"awa@example.com",
"lamin@example.com"
]
}'- Result: The message is sent as plain text: the first line becomes the subject (up to 120 characters), and each line becomes a paragraph. Every email carries an unsubscribe link.
How recipients are cleaned
- Invalid numbers or addresses are dropped, not rejected. If nothing valid is left, the request answers 400.
- Phone numbers are normalised to E.164 first, so two spellings of one number are sent once.
- SMS numbers in countries we do not deliver to are dropped.
- Email addresses that unsubscribed from your workspace are removed before counting — they are never charged or sent.
- An address that unsubscribes after the broadcast was accepted, for example while it waits for scheduledAt, is checked again at send time: it is not emailed and counts as failed with the reason suppressed.
totalCount is the list after cleaning, not what you posted. Compare it with your own count to see how many were dropped.
