Documentation overview
Read these documents to connect your system to our servers and buy numbers automatically. Prices, stock and balance are exactly the same as in the bot. All amounts are in USD.
๐ How to get an API key?
- Open our Telegram bot โ it is the only way to get a key.
- Accept the terms, then press ๐ API in the main menu and copy your key.
- Top up the balance in the bot (๐ฐ My account โ ๐ณ Top up) โ API purchases use the same balance.
Base URL
Authentication
Send the key in the X-Api-Key header (recommended โ keys in URLs end up in server logs) or as the api_key parameter. Never share your key; if it leaks, press โป๏ธ Change key in the bot.
Methods
All methods: GET (or POST) to the base URL with the action parameter.
# getBalance
Your current balance and today's API usage.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_key | String | Yes | Your API key (or the X-Api-Key header) |
| action | String | Yes | Put: getBalance |
{
"ok": true,
"balance": 12.5,
"spent": 3.2,
"currency": "USD",
"api_usage": {"requests_today": 41, "limit": 5000, "remaining": 4959}
}
# getCountries
All countries on sale, sorted by price. stock โ available numbers (null โ available, exact amount unknown).
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_key | String | Yes | Your API key (or the X-Api-Key header) |
| action | String | Yes | Put: getCountries |
{
"ok": true, "currency": "USD", "count": 182,
"countries": [
{"country": "BD", "dial": "880", "name": "Bangladesh", "price": 0.35, "stock": 2146},
{"country": "KE", "dial": "254", "name": "Kenya", "price": 0.42, "stock": null}
]
}
# getNumber
Buy a number. The price is charged only if a number is issued; if the provider issues none, nothing is charged.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_key | String | Yes | Your API key (or the X-Api-Key header) |
| action | String | Yes | Put: getNumber |
| country | String | Yes | Country, ISO 3166-1 alpha-2 (e.g. KE) |
| max_price | Number | No | Highest price you accept. If the current price is higher you get PRICE_TOO_HIGH and nothing is charged. If omitted, the price from getCountries is the limit. |
| request_id | String | No | Your unique order id (6โ64 chars: A-Z a-z 0-9 . _ -). Repeating a request with the same id returns the same answer instead of buying again โ safe to retry after timeouts. |
{
"ok": true,
"id": 1532,
"phone": "8801712345678",
"country": "BD",
"price": 0.35,
"balance": 12.15
}
# getCode
Login code of your number. status: wait โ not yet (expires_in seconds left), ok โ code and 2FA password (may be null), cancelled โ no code in time.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_key | String | Yes | Your API key (or the X-Api-Key header) |
| action | String | Yes | Put: getCode |
| id | Integer | Yes | Number id from getNumber |
{"ok": true, "id": 1532, "phone": "8801712345678", "status": "wait", "expires_in": 1650}
{"ok": true, "id": 1532, "phone": "8801712345678", "status": "ok", "code": "52814", "password": "x7kq2"}
# getStatus
Number status from our database โ instant, no provider request. Same fields as the callback.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_key | String | Yes | Your API key (or the X-Api-Key header) |
| action | String | Yes | Put: getStatus |
| id | Integer | Yes | Number id from getNumber |
{
"ok": true, "id": 1532, "phone": "8801712345678", "country": "BD",
"price": 0.35, "status": "ok", "code": "52814", "password": null,
"refunded": 0.0, "created_at": "2026-10-14 10:15:02"
}
# setCallback
Set the URL where we POST the code (or the cancellation) as soon as it arrives. Empty url disables it. Also in the bot: ๐ API โ ๐ Callback URL.
| Parameter | Type | Required | Description |
|---|---|---|---|
| api_key | String | Yes | Your API key (or the X-Api-Key header) |
| action | String | Yes | Put: setCallback |
| url | String | No | Public https:// URL (port 443, up to 255 chars) |
{"ok": true, "callback": "https://example.com/hook"}
Callback
When a code arrives or a number is cancelled we send POST with JSON (fields as in getStatus + event: code / cancelled). Verify the X-Signature header: hex HMAC-SHA256 of the raw body with your API key. Answer with any 2xx โ otherwise we retry up to 4 times. Handle it idempotently by id.
POST https://example.com/hook
Content-Type: application/json
X-Signature: 5f0cโฆe91a
{"event": "code", "ok": true, "id": 1532, "phone": "8801712345678", "country": "BD", "price": 0.35,
"status": "ok", "code": "52814", "password": null, "refunded": 0.0, "created_at": "2026-10-14 10:15:02"}
Examples
Buy a number and wait for the code:
# 1) buy curl -H "X-Api-Key: YOUR_API_KEY" "https://moonum-tg.com/?action=getNumber&country=BD&max_price=0.40&request_id=order-1001" # 2) code (repeat every 5โ10 s while status = wait) curl -H "X-Api-Key: YOUR_API_KEY" "https://moonum-tg.com/?action=getCode&id=1532"
<?php
$key = 'YOUR_API_KEY';
function api(array $q) {
global $key;
$ctx = stream_context_create(['http' => ['header' => "X-Api-Key: $key\r\n"]]);
return json_decode(file_get_contents('https://moonum-tg.com/?' . http_build_query($q), false, $ctx), true);
}
$n = api(['action' => 'getNumber', 'country' => 'BD', 'max_price' => 0.40, 'request_id' => 'order-1001']);
if (!$n['ok']) exit($n['error']);
echo "Number: {$n['phone']}\n";
do {
sleep(7);
$c = api(['action' => 'getCode', 'id' => $n['id']]);
} while ($c['ok'] && $c['status'] === 'wait');
echo $c['status'] === 'ok' ? "Code: {$c['code']}\n" : "No code\n";
import time, requests
API = 'https://moonum-tg.com/'
H = {'X-Api-Key': 'YOUR_API_KEY'}
n = requests.get(API, headers=H, params={'action': 'getNumber', 'country': 'BD',
'max_price': 0.40, 'request_id': 'order-1001'}).json()
if not n['ok']:
raise SystemExit(n['error'])
print('Number:', n['phone'])
while True:
time.sleep(7)
c = requests.get(API, headers=H, params={'action': 'getCode', 'id': n['id']}).json()
if not c['ok'] or c['status'] != 'wait':
break
print('Code:', c.get('code'))
Errors
On error: {"ok": false, "error": "CODE", "message": "..."} with a matching HTTP status.
| BAD_KEY | Key missing or invalid (401) |
| API_BLOCKED | API access blocked by admin (403) |
| BANNED | Account blocked (403) |
| MAINTENANCE | Service temporarily off (503) |
| BAD_ACTION | Unknown action (400) |
| BAD_COUNTRY ยท BAD_MAX_PRICE ยท BAD_REQUEST_ID ยท BAD_URL | Invalid parameter (400) |
| NO_NUMBERS | Country not available (404) |
| PRICE_TOO_HIGH | Price above max_price, current price included (409) |
| NO_BALANCE | Not enough balance, price and balance included (402) |
| NO_NUMBER_ISSUED | Provider issued no number, nothing charged โ retry later (503) |
| IN_PROGRESS | Same request_id is still being processed (409) |
| REQUEST_ID_USED | request_id already used for another action (409) |
| NOT_FOUND | Number id not found (404) |
| RATE_LIMIT | Too many requests: max 300 / 10 s and 1200 / 60 s, see Retry-After (429) |
| DAILY_LIMIT | Daily request limit reached, resets tomorrow (429) |
| PROVIDER_ERROR | Code check failed, retry (502) |
| INTERNAL | Unexpected server error โ check getStatus / getBalance before retrying (500) |
| PENDING_REVIEW | Rare: number reserved but not saved โ do not retry, contact support (500) |
Important rules
- If the code does not arrive within 30 minutes, the number is cancelled. The payment is not refunded โ the number counts as delivered.
- If no number is issued at all, nothing is charged.
- Numbers may be frozen or banned by Telegram โ this is not grounds for a refund.
- Using the API means you accept the bot's Terms of Use.
๐ฌ Support
Questions, top-ups and partnership โ write to us in Telegram.