Skip to content

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]
Hold "Ctrl" to enable pan & zoom

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:

  • 01712345678
  • 8801712345678
  • +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:

  1. tenant username;
  2. requested sender CLI;
  3. SMS type and masking-compatible channel;
  4. active public sender configuration;
  5. carrier/IPTSP credential;
  6. tenant/channel/operator billing rate.

Price is calculated per recipient:

(segmentCount × ratePerSegment) + diPrice

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_progress and 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.