Developer API quick start
Buy numbers and read codes from your own software. Create a key, check prices, buy a number, wait for the SMS and finish, step by step.
On this page
The SmsGrab developer API gives your software the same numbers as the app, through a REST API that speaks JSON. It is a paid product with its own developer prices, paid from your normal SmsGrab balance and covered by the same automatic refunds.
Who can use it
- An e-mail account with a confirmed address. Guest accounts cannot create keys.
- An account in good standing.
1. Create an API key
Open Account > Developers on the website, or Settings > Developer API in the app, and create a key. For security you confirm with your password, and with your two-step code if it is on. Choose the read scope for read-only tools, or read and purchase to buy numbers.
The key starts with sgk_ and is shown only once. Keep it in your server's secret storage. See API keys and security.
2. Authenticate
The base URL is https://smsgrab.com/api/dev/v1. Send the key as a bearer token, or in the X-Api-Key header:
GET /api/dev/v1/balance HTTP/1.1
Host: smsgrab.com
Authorization: Bearer sgk_your_key_here
Keys belong on servers. Never put them into a website, a browser extension or an app you give to other people.
3. Check your balance and prices
export SMSGRAB_KEY="sgk_your_key_here"
curl -s https://smsgrab.com/api/dev/v1/balance \
-H "Authorization: Bearer $SMSGRAB_KEY"
curl -s "https://smsgrab.com/api/dev/v1/prices?service=whatsapp&country=indonesia" \
-H "Authorization: Bearer $SMSGRAB_KEY"
Money is always given in minor units of USD, so 18 means 0.18 USD. price_minor is your developer price and retail_price_minor the app price.
{ "currency": "USD", "markup_percent": 80,
"items": [ { "service_id": "whatsapp", "country_id": "indonesia", "price_minor": 18,
"retail_price_minor": 25, "available_numbers": 30412 } ] }
4. Buy a number
curl -s -X POST https://smsgrab.com/api/dev/v1/activations \
-H "Authorization: Bearer $SMSGRAB_KEY" \
-H "Idempotency-Key: order-7f3c2a" \
-H "Content-Type: application/json" \
-d '{"service":"whatsapp","country":"indonesia","max_price_minor":20}'
serviceandcountrytake our ids, such aswhatsappandindonesia. Countries also accept ISO codes such asID.max_price_minorprotects you: if the price has gone up, nothing is charged and you get409 PRICE_CHANGED.Idempotency-Keymakes retries safe. Repeating the request with the same key returns the first result instead of buying twice.
The answer is 201 Created with the activation:
{ "id": "5c1d0c2e-8a41-4f7e-9d7a-2f1d9f1b8c11", "compat_id": 100000123, "status": "WAITING_SMS",
"service_id": "whatsapp", "country_id": "indonesia", "phone_number": "+6281234567890",
"price_minor": 18, "currency": "USD",
"created_at": "2026-09-27T10:05:00.000Z", "expires_at": "2026-09-27T10:25:00.000Z",
"refunded": false, "refund_minor": 0, "sms": [] }
5. Wait for the SMS
Instead of polling in a tight loop, let the API hold the request until something changes, for up to 30 seconds:
curl -s "https://smsgrab.com/api/dev/v1/activations/100000123?wait=25" \
-H "Authorization: Bearer $SMSGRAB_KEY"
When a message arrives, status becomes CODE_RECEIVED and sms holds every message so far:
{ "status": "CODE_RECEIVED",
"sms": [ { "code": "482913", "text": "Your WhatsApp code is 482-913", "sender": "WhatsApp",
"received_at": "2026-09-27T10:06:12.004Z" } ] }
Prefer push to polling? Set up webhooks.
6. Finish or cancel
curl -s -X POST https://smsgrab.com/api/dev/v1/activations/100000123/finish \
-H "Authorization: Bearer $SMSGRAB_KEY"
curl -s -X POST https://smsgrab.com/api/dev/v1/activations/100000123/cancel \
-H "Authorization: Bearer $SMSGRAB_KEY"
- finish once you have used the code. It is accepted only after a code has arrived.
- cancel while you are still waiting for the first code. The full price is refunded.
- If you do nothing, a number without a code expires after 20 minutes and is refunded automatically.
Status values
| Status | Meaning |
|---|---|
WAITING_SMS |
Bought, waiting for the first message |
CODE_RECEIVED |
At least one message has arrived |
COMPLETED |
Finished by you, or when the time ran out after a code |
CANCELLED |
Cancelled before a code, refunded |
EXPIRED |
No code within 20 minutes, refunded |
Errors
Every error has the same shape. Act on code and reason, and ignore reasons you do not know yet:
{ "code": "NO_NUMBERS_AVAILABLE", "message": "No numbers available for this service and country", "reason": "OUT_OF_STOCK" }
Common cases are 402 INSUFFICIENT_BALANCE, 409 NO_NUMBERS_AVAILABLE, 409 PRICE_CHANGED, 422 with ACTIVATION_LIMIT_REACHED (at most 100 numbers can wait at once per account) and 429 RATE_LIMITED with a Retry-After header.
The complete reference is in the developer documentation.
Was this article helpful?
Thanks! Glad it helped.