Direct Messaging¶
Direct messaging supports application-triggered OTP, transactional, and promotional SMS without creating a managed campaign. A single request can contain 1–5,000 Bangladesh recipients.
Message types and priority¶
| SMS type | Intended use | Outbound behavior | Priority |
|---|---|---|---|
OTP |
Authentication and one-time codes | One recipient per provider request | 1, highest |
TRANSACTIONAL |
Account alerts, receipts and service notifications | One recipient per provider request | 2 |
PROMOTIONAL |
Marketing content | Up to 999 compatible recipients per provider request | 3 |
Promotional submission requires an operator/MNPSP-approved campaignId. This approval identifier is not the platform campaign UUID.
Acceptance pipeline¶
flowchart TD
A[Signed-in client submits a request] --> V[Check type, sender, content and recipients]
V --> N[Format Bangladesh phone numbers]
N --> O[Identify each mobile operator]
O --> R[Choose the sender and delivery route]
R --> E[Count SMS parts]
E --> P[Calculate the total cost]
P --> B[Check and charge the balance]
B --> D[Save and queue the messages]
D --> A2[Return 201 PENDING with messageId]
The platform checks every recipient before accepting the request. Each phone number must be valid, belong to a supported operator, and have an available sender, route and price. If any recipient fails these checks, the entire request is rejected.
A 201 response means the request has been checked, charged and queued for sending. It does not mean the messages have been sent or delivered.
Bangladesh recipient handling¶
The platform accepts common local/international forms such as:
017123456788801712345678+8801712345678
They are normalized to the 8801… form and classified as:
| Mobile operator | Prefixes |
|---|---|
Grameenphone (GP) |
88017, 88013 |
Robi Axiata and Airtel (RB) |
88018, 88016 |
Banglalink (BL) |
88019, 88014 |
Teletalk (TT) |
88015 |
If a phone number is invalid or its prefix is not supported, the entire request is rejected. The platform does not silently skip that recipient.
How message length affects SMS parts¶
The platform automatically chooses how to encode the message. One segment is one billable SMS part. Longer messages are split into multiple parts, and each part is charged.
| Encoding | Common content | One-part limit | Limit per part in a longer message |
|---|---|---|---|
| GSM-7 | Basic English letters, numbers and common symbols | 160 units | 153 units |
| UCS-2 | Bangla and other characters outside GSM-7 | 70 units | 67 units |
GSM-7 counts text in seven-bit units called septets. Most basic English characters use one unit, while characters such as {, }, ^ and € use two. For example, 160 ordinary GSM-7 characters fit in one SMS part, while 161 require two parts.
UCS-2 is used for Bangla and other non-GSM characters. Most characters use one UTF-16 unit, although some symbols such as emoji use two. A message with 70 units fits in one SMS part, while 71 units require two parts.
The response shows the selected encoding and number of SMS parts. Small content changes, including punctuation or Unicode characters, can therefore change the total cost.
Sender and price resolution¶
For every operator group, the platform resolves:
- tenant username;
- requested sender CLI;
- SMS type and masking-compatible channel;
- active public sender configuration;
- carrier/IPTSP credential;
- tenant/channel/operator billing rate.
Price is calculated per recipient:
DI price is charged once per recipient. The platform records the original route, the route used for delivery and the charge details so operators can review them later.
Retrying a submission safely¶
Include an Idempotency-Key with each request to prevent duplicate messages and charges when a submission must be retried.
- The key belongs to the signed-in username and remains valid for 24 hours.
- Repeating the same request with the same key returns the original response without sending or charging again.
- Using the same key for different request details returns
409 idempotency_mismatch. - If the first request is still running, another request with that key returns
409 idempotency_in_progressand asks the client to retry after two seconds. - If the request fails, the key is released so a corrected request can be submitted.
An order or transaction ID is a good key. Never reuse it for an unrelated message.
Checking message status¶
Clients can check a request using its messageId. A client can only see its own messages. By default, the response shows summary counts. Set includeRecipients=true to see each recipient's phone number, provider reference, error and delivery time for up to 5,000 recipients.
| Recipient results | Message status |
|---|---|
| At least one message is waiting or has been sent to the provider | PENDING |
| Every message was delivered | DELIVERED |
| Every message failed, expired or was rejected | FAILED |
The final results are mixed, or include NOT_AVAILABLE |
PARTIAL |
Recipient details contain personal data. Only retrieve, log or store them when needed.
Delivery results and refunds¶
Messages are sent after the request is accepted. The platform then checks delivery reports from the provider and refunds eligible failures:
- If a group of messages is rejected before it can be sent, the cost of that group can be refunded.
- If a recipient receives a final failed delivery result, that recipient's cost can be refunded.
- If a refund attempt fails, the platform retries it up to ten times. An operator must review any refund that still fails.
If no final delivery result is available after all status checks, the message becomes NOT_AVAILABLE and is not automatically refunded. Response code 9099 is treated as delivered and remains charged. See Delivery, DLR and Refunds.
See the Messaging API and SMS router architecture.