SMS API
Send transactional SMS (OTP codes, alerts) worldwide with a single HTTP request. You compose the text — we deliver it to the number.
https://sendoor.org/api/v1Authentication
All requests are authenticated with an API key in the Authorization header. Create a key in your dashboard → API keys.
Authorization: Bearer sk_live_xxx⚠️ Keep the key secret — it grants access to your balance. Revoke a compromised key in the dashboard.
/sms/sendSend SMS
Sends a single message. Charges the cost to your balance.
Body parameters (JSON)
| field | type | required | — |
|---|---|---|---|
| phone | string | yes | Phone number in E.164 format, e.g. +919800000000 |
| text | string | yes | Message text (delivered to the recipient as-is) |
| sender | string | no | Sender ID. Defaults to SENDOOR |
| reference | string | no | Your identifier for idempotency (deduplication) |
Request example
curl -X POST https://sendoor.org/api/v1/sms/send \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"phone": "+919800000000",
"text": "Your code is 1234"
}'Response 201 Created
{
"id": "8f3a1c2e-...",
"status": "sent",
"parts": 1,
"price": "0.1000"
}/messages/sendSend a messenger message
Deliver a message over WhatsApp, Telegram, Viber or IMO. Same billing model as SMS — you are charged the per-channel price and refunded automatically if delivery fails. Each channel is enabled separately on your API key; a key without a channel's access gets 403.
Body parameters (JSON)
| field | type | required | — |
|---|---|---|---|
| channel | string | yes | whatsapp | telegram | viber | imo |
| phone | string | yes | Recipient in E.164, e.g. +919800000000 |
| text | string | yes | Message body |
| image_url | string | no | Optional media URL attached to the message |
| reference | string | no | Your idempotency key (deduplicates retries) |
Request example
curl -X POST https://sendoor.org/api/v1/messages/send \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"channel": "whatsapp",
"phone": "+919800000000",
"text": "Your code is 1234",
"image_url": "https://example.com/pic.jpg"
}'Response 201 Created
{
"id": "8f3a1c2e-...",
"channel": "whatsapp",
"status": "sent",
"price": "0.0500"
}Delivery status is retrieved the same way as SMS — GET /sms/{id}.
/sms/{id}Message status
Returns the current delivery status (refreshed automatically).
curl https://sendoor.org/api/v1/sms/MESSAGE_ID \
-H "Authorization: Bearer sk_live_xxx"Response
{
"id": "8f3a1c2e-...",
"phone": "+919800000000",
"status": "delivered",
"parts": 1,
"price": "0.1000",
"reference": "order-42",
"createdAt": "2026-06-08T12:00:00.000Z"
}/balanceBalance
Your account's current balance.
curl https://sendoor.org/api/v1/balance \
-H "Authorization: Bearer sk_live_xxx"Response
{ "balance": "42.50", "currency": "USD" }/countriesYour available countries
Returns the countries enabled for your account, with prices. Just send the full E.164 number — the country is detected automatically.
curl https://sendoor.org/api/v1/countries \
-H "Authorization: Bearer sk_live_xxx"Response
{
"countries": [
{ "iso": "IN", "name": "India", "dial": "91", "price": "0.1000" }
],
"defaultPrice": null,
"currency": "USD"
}Status values
| Status | Description |
|---|---|
| pending | Accepted, preparing to send |
| sent | Handed to the carrier |
| delivered | Delivered to the recipient |
| failed | Not delivered (error) |
| expired | Delivery window expired |
Errors
On error, the matching HTTP code and a { error, message } body are returned.
| HTTP | error | Description |
|---|---|---|
| 400 | bad_request / validation | Invalid data (phone, text) |
| 401 | unauthorized | Missing or invalid API key |
| 402 | insufficient_funds | Not enough balance |
| 403 | forbidden | Key lacks the required scope |
| 404 | not_found | Message not found |
| 502 | provider_error | Delivery route error |
Idempotency
Pass a unique reference field in the send request. A repeated request with the same reference won't create a duplicate or charge again — the existing message is returned. Handy for network-timeout retries.
Countries
The country is detected automatically from the number. Available destinations and prices are configured by your manager. The ISO code is the one used in pricing.
| ISO | Country | Dial |
|---|---|---|
| IN | India | +91 |
| UA | Ukraine | +380 |
| PL | Poland | +48 |
| DE | Germany | +49 |
| GB | United Kingdom | +44 |
| US | United States | +1 |
| ES | Spain | +34 |
| FR | France | +33 |
| IT | Italy | +39 |
| NL | Netherlands | +31 |
| PT | Portugal | +351 |
| TR | Turkey | +90 |
| AE | United Arab Emirates | +971 |
| SA | Saudi Arabia | +966 |
| EG | Egypt | +20 |
| NG | Nigeria | +234 |
| KE | Kenya | +254 |
| ZA | South Africa | +27 |
| PK | Pakistan | +92 |
| BD | Bangladesh | +880 |
| ID | Indonesia | +62 |
| PH | Philippines | +63 |
| VN | Vietnam | +84 |
| TH | Thailand | +66 |
| MY | Malaysia | +60 |
| SG | Singapore | +65 |
| CN | China | +86 |
| JP | Japan | +81 |
| KR | South Korea | +82 |
| BR | Brazil | +55 |
| MX | Mexico | +52 |
| AR | Argentina | +54 |
| CO | Colombia | +57 |
| CL | Chile | +56 |
| PE | Peru | +51 |
| KZ | Kazakhstan | +7 |
| UZ | Uzbekistan | +998 |
| AZ | Azerbaijan | +994 |
| GE | Georgia | +995 |
| MD | Moldova | +373 |
| RO | Romania | +40 |
| CZ | Czechia | +420 |
| SK | Slovakia | +421 |
| HU | Hungary | +36 |
| BG | Bulgaria | +359 |
| GR | Greece | +30 |
| AT | Austria | +43 |
| CH | Switzerland | +41 |
| BE | Belgium | +32 |
| SE | Sweden | +46 |
| NO | Norway | +47 |
| DK | Denmark | +45 |
| FI | Finland | +358 |
| IE | Ireland | +353 |
| IL | Israel | +972 |
| QA | Qatar | +974 |
| KW | Kuwait | +965 |
| MA | Morocco | +212 |
| DZ | Algeria | +213 |
| GH | Ghana | +233 |
| AU | Australia | +61 |
| NZ | New Zealand | +64 |
| CA | Canada | +1 |
sendoor.org:2775SMPP connectivity
For platforms with their own SMS engine we provide a standard SMPP 3.4 interface. Pricing, enabled countries, balance and refunds are the same as for the HTTP API — you can use both channels in parallel on a single account.
Credentials (system_id + password) are issued by your account manager. They are separate from your API key.
Connection parameters
| Parameter | Value | Note |
|---|---|---|
| host | sendoor.org | TCP, no TLS |
| port | 2775 | |
| version | SMPP 3.4 | bind_transceiver / transmitter / receiver |
| system_id / password | issued by your manager | up to 2 concurrent bind sessions (can be raised) |
| throughput | 10 SMS/sec | default; exceeding it → ESME_RTHROTTLED |
| enquire_link | every 30 s recommended | supported |
Notes
- •Destination numbers in international (E.164) format, e.g. 919800000000.
- •Encodings: GSM 7-bit and UCS-2 (data_coding 8) for Unicode.
- •Long SMS: concatenation via UDH (8/16-bit ref) or message_payload — parts are reassembled and billed as one message.
- •DLR: set registered_delivery=1 to receive deliver_sm with a standard receipt (stat: DELIVRD / UNDELIV / EXPIRED). Undelivered messages are refunded automatically.
- •The message_id from submit_sm_resp is the same id as in the HTTP API — you can also check status via GET /sms/{id}.
Error codes (command_status)
| Code | Constant | Reason |
|---|---|---|
| 0x0000000B | ESME_RINVDSTADR | Country not enabled for your account, or invalid number |
| 0x00000014 | ESME_RMSGQFUL | Insufficient balance |
| 0x00000058 | ESME_RTHROTTLED | Throughput limit exceeded (SMS/sec) |
| 0x0000000E | ESME_RINVPASWD | Invalid system_id / password |
| 0x00000045 | ESME_RSUBMITFAIL | Delivery route error — retry later |