Documentation
Sign inGet started

Send a batch of SMS messages

POST
/v1/sms/batches
curl -X POST "https://us1.platform.bird.com/v1/sms/batches" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "to": "+15551111111",
      "from": "+15557654321",
      "text": "Hi Alice!",
      "category": "marketing"
    },
    {
      "to": "+15552222222",
      "from": "+15557654321",
      "text": "Hi Bob!",
      "category": "marketing"
    }
  ]'
Sends up to 100 independent SMS messages in one request. Each item is a complete send request with its own recipient, content, id, status, and cost. For a single message, use Send an SMS message instead.
Acceptance is all-or-nothing: every item is validated before any is queued, and one invalid item rejects the whole batch with a 422 (nothing is sent). A batch from a workspace with no wallet balance fails with a 402. The 202 response lists the accepted messages in submission order; each delivers asynchronously and is tracked individually, like a single send.
Verzoekpayload
Array van objecten, elk met:
to
string
Recipient phone number in E.164 format (for example +15551234567). One recipient per message.
from
string
Sender to send from: an E.164 number (+15557654321), an alphanumeric sender ID (1-11 letters, digits, or spaces, for example MyBrand), or a short code (5-6 digits). A numeric sender must be a number your workspace owns; an alphanumeric sender is accepted where the destination country permits one. Required on a free-text send: omitting it returns a 422 SMSNoEligibleSender. Not accepted alongside template, which selects its sender automatically.
text
string
verplicht
Free-text message body. Required unless template is supplied (the two are mutually exclusive). At least 1 character, up to a 12-segment cap (roughly 1836 GSM-7 or 804 UCS-2 characters). Bird does not truncate; a body exceeding 12 segments is rejected with a 422. The limit is on segment count, not characters, because GSM-7 and UCS-2 encodings differ in characters per segment.
category
object
Content classification. Tells Bird and carriers why you're sending; per-country compliance rules (opt-out policy, quiet hours) key on it as they roll out. Required on a free-text send; omit it on a template send, where the category is derived from the template.
validity_period
integer
Preview feature: how long, in seconds (60-172800), Bird keeps trying to deliver before the message transitions to expired. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
tags
array of object
Structured {name, value} labels for filtering and analytics. Tags become first-class query dimensions: filter the list endpoint by tag name, slice analytics by tag, and surface in webhook payloads. Maximum 20 tags per send. Use tags for low-cardinality dimensions (category, experiment_variant). For arbitrary structured context you do not need as a filter dimension, use metadata instead.
Onderliggende parameters tonen
tags.name
string
verplicht
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
tags.value
string
verplicht
Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
metadata
object
Arbitrary JSON object stored on the message, returned on API reads, and echoed in webhook payloads. Maximum 2 KB serialized. Use metadata for per-send context like internal IDs and foreign keys. For low-cardinality filterable labels, use tags instead.
media_urls
array of string
Preview feature: multimedia (MMS) attachments. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
messaging_profile_id
string
Preview feature: sender selection from a messaging profile pool. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
scheduled_at
string
Preview feature: send-later scheduling. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
template
object
verplicht
Send using a stored template instead of free text. Mutually exclusive with text; the message category is derived from the template, so from, category, and media_urls are not accepted alongside it.
Onderliggende parameters tonen
template.id
string
verplicht
The template to send, by its id.
template.name
object
verplicht
The template to send, by its name handle (for example bird_otp_verification). Browse the available templates and their variables with the templates endpoint.
template.language
string
Language tag (BCP 47, for example fr or pt-BR) selecting the localized body. Falls back to the closest available language, then English, when the exact tag is not stocked. Omit for English.
template.parameters
object
Values for the template's variables, keyed by variable name. The accepted keys and their formats are fixed per template (the template's variables on the templates endpoint). A missing required variable, an undeclared key, a value that does not match its variable's format, or a serialized payload over 16 KB each return a 422.
broadcast_id
string
Preview feature: broadcast correlation. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
campaign_id
string
Preview feature: campaign correlation for analytics. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
audience_id
string
Preview feature: audience-targeted sends. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
contact_id
string
Preview feature: contact-targeted sends. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
topic_id
string
Preview feature: topic-gated sends. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
max_price_per_segment
number
Preview feature: per-segment price ceiling. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
personalization
object
Preview feature: per-recipient substitution for batch sends. Currently unavailable; supplying this field returns 422 SMSUnsupportedFeature.
track_clicks
boolean
Preview feature: link click tracking. Defaults to false. Currently unavailable; setting this to true returns 422 SMSUnsupportedFeature.
Response Payload
data
array of object
verplicht
One entry per message in the batch, in submission order.
Onderliggende attributen tonen
data.id
string
verplicht
ID of the message (sms_-prefixed), assigned when the send is accepted. Pass it as message_id to the get-message endpoint.
data.direction
string
verplicht
Whether the message was sent from a Bird sender (outbound) or received from a subscriber (inbound).
Possible values: outbound, inbound
data.status
object
verplicht
data.to
string
verplicht
Recipient phone number in E.164 format.
data.from
string
verplicht
Sender the message was sent from: an E.164 number, an alphanumeric sender ID, or a short code.
data.text
string
verplicht
The message body as sent. For a template send, this is the rendered text after parameter substitution.
data.category
nullable string
Content classification supplied on the send. Null for inbound messages.
data.segments
object
verplicht
Segment breakdown for the body.
Onderliggende attributen tonen
data.segments.count
integer
verplicht
Number of segments the body is split into. Each segment is a billable unit.
data.segments.encoding
string
verplicht
Encoding used for the body. GSM_7BIT fits 160 characters in a single segment (153 per part when multi-segment); UCS2 is used when the body contains any character outside the GSM 03.38 alphabet (emoji, CJK, some accented characters) and fits 70 characters in a single segment (67 per part when multi-segment).
Possible values: GSM_7BIT, UCS2
data.segments.characters
integer
verplicht
Character count of the body under the selected encoding.
data.cost
nullable object
Cost of the message. Null until the message has been priced.
Onderliggende attributen tonen
data.cost.currency_code
string
ISO 4217 currency code for the cost amount. Omitted when the cost is not denominated in a currency (for example a zero-priced internal send).
data.cost.amount
string
verplicht
Total cost as a decimal string: the per-segment rate multiplied by the segment count, plus any surcharges.
data.cost.breakdown
object
Per-component cost breakdown. Returned on single-message reads; omitted from list rows.
Onderliggende attributen tonen
data.cost.breakdown.per_segment
string
verplicht
Per-segment price as a decimal string.
data.cost.breakdown.segments
integer
verplicht
Number of billable segments.
data.cost.breakdown.country_code
string
verplicht
ISO 3166-1 alpha-2 destination country the price was resolved for.
data.cost.breakdown.carrier_surcharge
string
verplicht
Carrier surcharge component as a decimal string (for example US 10DLC fees). 0.0000 when none applies.
data.tags
array of object
Structured {name, value} filter labels applied to this message.
Onderliggende attributen tonen
data.tags.name
string
verplicht
Tag name. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 32 characters.
data.tags.value
string
verplicht
Tag value. ASCII letters, digits, underscore, and hyphen only. Case-sensitive. Maximum 64 characters.
data.metadata
object
Arbitrary JSON metadata stored on the message and echoed in webhook payloads.
data.validity_period
integer
How long, in seconds, Bird keeps trying to deliver before the message transitions to expired.
data.carrier
nullable string
Carrier that handled the message, when known. Populated once a delivery receipt identifies it.
data.mcc_mnc
nullable string
Mobile country code and mobile network code of the carrier, when known.
data.last_error
nullable object
Failure detail on a terminally failed or rejected message. Present only when the message failed.
Onderliggende attributen tonen
data.last_error.code
string
verplicht
Bird-stable failure reason. invalid_destination: the number is not assigned, ported out, or malformed. unreachable: handset off or out of coverage. blocked_by_carrier: the carrier filtered the message. blocked_by_recipient: the recipient device blocked the sender. landline_unreachable: the destination is a landline that does not accept SMS. content_rejected: the carrier rejected the content. sender_unregistered: the sender is not registered for the destination. recipient_opted_out: the recipient is on a suppression list. provider_unavailable: an upstream failure after retries. insufficient_balance: the workspace wallet had insufficient balance to send the message. unknown: an unmapped failure.
Possible values: invalid_destination, unreachable, blocked_by_carrier, blocked_by_recipient, landline_unreachable, content_rejected, sender_unregistered, recipient_opted_out, provider_unavailable, insufficient_balance, unknown
data.last_error.description
string
verplicht
Human-readable explanation of the failure.
data.last_error.carrier_error_code
nullable string
Raw carrier-supplied error code, when available, for low-level debugging.
data.last_error.occurred_at
string
verplicht
When the failure occurred.
data.created_at
string
verplicht
When the message was accepted (outbound) or received (inbound).
data.sent_at
nullable string
When the message was handed to the carrier. Null until then.
data.delivered_at
nullable string
When delivery was confirmed. Null until then.
summary
object
verplicht
Aggregate result for the batch.
Onderliggende attributen tonen
summary.accepted_count
integer
verplicht
Number of messages accepted in the batch. Acceptance is all-or-nothing, so this equals the number of messages submitted.