Developer documentation
ড্যাশবোর্ড
Errors
Every error, from authentication to validation to balance, uses the same response envelope. Branch on the stable error_code, never on the localized message: one HTTP status can have several causes. errors is always an object, and data carries the values you need to act, such as amounts and limits.
Error catalog
error_code |
HTTP | Errors key | Message |
|---|---|---|---|
invalid_api_key |
401 |
authorization
|
The API key is invalid |
api_key_revoked |
401 |
authorization
|
The API key has been revoked |
api_key_expired |
401 |
authorization
|
The API key has expired |
account_inactive |
403 |
account
|
This account is not active |
unauthenticated |
401 |
authorization
|
Authentication is required |
insufficient_balance |
402 |
balance
|
Your wallet balance is too low for this request |
ip_not_allowed |
403 |
authorization
|
Requests from this IP address are not allowed for this API key |
insufficient_scope |
403 |
scope
|
This API key does not have the required scope |
wallet_inactive |
403 |
wallet
|
Your wallet is not active |
service_disabled |
403 |
service
|
This service is not enabled for your account |
forbidden |
403 |
permission
|
This action is unauthorized |
not_found |
404 |
resource
|
The requested resource was not found |
idempotency_key_reused |
409 |
idempotency_key
|
This idempotency key was already used with a different request |
request_in_progress |
409 |
idempotency_key
|
A request with this idempotency key is still being processed |
validation_error |
422 | input path | The given data was invalid |
rate_limited |
429 |
rate_limit
|
Too many requests |
http_error |
400 |
server
|
Something went wrong, please try again |
server_error |
500 |
server
|
Something went wrong, please try again |
service_unavailable |
503 |
service
|
This service is temporarily unavailable |
service_restricted |
403 |
service
|
Your account is restricted from this service, please contact support |
content_rejected |
422 |
content
|
This message was not sent because its content breaks our SMS rules, if it is not harmful please contact support |
Evaluation order
Checks run in a fixed order and the first failure is returned, so you always get the most fundamental problem first.
- Authentication and IP allowlist:
401or403 ip_not_allowed. - Rate limit:
429 rate_limited. - Unknown resource: an
{id}in the path that does not exist or belongs to another account returns404 not_found. - Idempotency: a stored response is replayed, or
409. - Service switch and service access:
503 service_unavailable,403 service_disabledor403 service_restricted. - Scope:
403 insufficient_scope. - Validation:
422 validation_error, with every field error at once. - Content check:
422 content_rejected. The response never says which words matched. If a normal, harmless message is rejected, contact support. - Wallet and balance, checked under the wallet lock:
403 wallet_inactiveor402 insufficient_balance.
A request that fails validation never reaches your wallet, so a 402 always means the payload is valid and only the balance is short.
Validation errors
Every problem with the request content is a 422 validation_error: invalid numbers, an empty or overlong body, an unapproved sender, too many recipients, an empty group. Errors are keyed by Laravel dot-notation input path (to.1, messages.2.body) and reported all together. Messages count positions from 1, so to.1 reads "Recipient #2".
{
"success": false,
"message": "Recipient #2 is not a valid Bangladeshi mobile number (and 2 more errors)",
"data": null,
"errors": {
"to.1": [
"Recipient #2 is not a valid Bangladeshi mobile number"
],
"to.4": [
"Recipient #5 is not a valid Bangladeshi mobile number"
],
"body": [
"The SMS body is 11 parts long; the maximum is 10 parts"
]
},
"code": 422,
"error_code": "validation_error",
"timestamp": "2026-09-26T10:00:00.000000Z"
}
Insufficient balance
Amounts are strings with two decimals, in BDT. Top up at least data.shortfall and retry; retrying with the same Idempotency-Key is safe because error responses are never stored.
{
"success": false,
"message": "Your wallet balance is too low for this request",
"data": {
"required": "3.24",
"available": "1.00",
"shortfall": "2.24",
"currency": "BDT"
},
"errors": {
"balance": [
"This request costs 3.24 BDT but your wallet balance is 1.00 BDT"
]
},
"code": 402,
"error_code": "insufficient_balance",
"timestamp": "2026-09-26T10:00:00.000000Z"
}
Authentication
{
"success": false,
"message": "The API key is invalid",
"data": null,
"errors": {
"authorization": [
"The API key is invalid"
]
},
"code": 401,
"error_code": "invalid_api_key",
"timestamp": "2026-09-26T10:00:00.000000Z"
}
Rate limit
{
"success": false,
"message": "Too many requests, retry after 12 seconds",
"data": {
"limit": 30,
"retry_after": 12
},
"errors": {
"rate_limit": [
"Too many requests, retry after 12 seconds"
]
},
"code": 429,
"error_code": "rate_limited",
"timestamp": "2026-09-26T10:00:00.000000Z"
}