Guides
Sending messages
How a batch is composed, how numbers are normalised, and what determines the number of segments you are billed for.
Everything is a batch
There is no single-message endpoint. Sending to one recipient is a batch of one, which means the same code path, the same idempotency guarantee and the same reporting whether you send to one person or a hundred thousand.
A batch takes between 1 and 100,000 recipients, and the message body may be up to 4,000 characters. Above 10,000 recipients the submission is processed asynchronously and the counts in the response arrive zeroed — see the batches reference for what to do about that.
Phone numbers
Numbers are accepted in either international or local form and normalised to E.164, with Burkina Faso as the default region. Local numbers from other countries must be sent in international form, since there is no way to guess which country they belong to.
A number that cannot be parsed is not an error. It becomes a rejection row inside an otherwise successful 202, with reason_code INVALID_MSISDN and a null msisdn — one bad number in a list of a thousand does not cost you the other 999.
Choosing a sender
The sender is what appears on the handset — a brand name like PRESTIGE, or a number. Its type is derived from the value rather than declared: anything non-numeric is alphanumeric, a long number is numeric, and a short number is a short code.
Check is_sendable before you send. A sender can be approved by SMSend and still not be registered with any operator, in which case it reads as APPROVED and every message sent with it fails after burning its full retry budget.
Message class
The class is required, and it is not a label. It decides queue priority, whether quiet hours apply, which frequency caps are enforced, and which suppression list is consulted.
| Value | Meaning |
|---|---|
TRANSACTIONAL | Triggered by something the recipient did — an order confirmation, a receipt, a delivery notice. Not subject to quiet hours or frequency caps. |
MARKETING | Promotional. Subject to quiet hours, daily and weekly frequency caps, and marketing opt-outs. |
OTP | One-time passcodes. Highest priority; never held back by quiet hours or caps. |
Merge tags
Put a tag in braces in the body and supply its value per recipient. One request then sends a different message to every person in it.
A tag with no matching attribute substitutes to an empty string, never to the literal text of the tag. The recipient is still sent to, and the warning does not appear in rejections — so check your attribute names, because a typo produces a silently truncated message rather than an error.
Encoding and segments
You are billed per segment, per recipient. Encoding and segmentation are computed from the rendered body, after merge tags have been substituted — so two recipients of the same batch can be billed differently.
| Encoding | Single segment | Per segment when concatenated |
|---|---|---|
GSM7 | 160 septets | 153 septets |
UCS2 | 70 UTF-16 code units | 67 UTF-16 code units |
One accented character doubles your bill
A single character outside the GSM-7 alphabet converts the entire message to UCS-2, which more than halves the capacity of every segment. In French copy this happens constantly: coût, août, and a name like Aïssata each flip that recipient's message on their own.
A few characters exist in GSM-7 but cost two septets each, because they are sent as an escape sequence:
An empty body counts as one segment and is charged. A two-unit character is never split across a segment boundary, so the packer may leave a segment one unit short and add a segment you did not expect.
Scheduling
Set scheduled_at to send later. It must be in the future, and the timezone is an IANA name — it defaults to your account's timezone, so set it explicitly if the campaign belongs to a different one.
A batch more than 30 minutes late does not fire. It is cancelled and refunded in full rather than sent at an unpredictable hour, on the reasoning that a delayed marketing message arriving at 3 a.m. is worse than no message.
Quiet hours and frequency caps for marketing are evaluated when the batch fires, not when you submit it. A campaign composed at 22:30 for a 09:00 send is not dropped.
Test sends
Set is_test to true to exclude a batch from campaign statistics. It is billed normally and really is delivered — it is a reporting flag, not a sandbox, and there is no mode in which SMSend accepts a message without sending it.