โšก Telegram numbers API

Virtual numbers for Telegram โ€” in your bot, automatically

Buy ready Telegram numbers and receive the login code through a simple HTTP API. 182 countries, prices in USD, the same balance as in our bot.

๐Ÿงฉ Simple

GET requests, JSON answers, one API key. Works from any language.

๐Ÿ›ก Safe

Money is charged only when a number is issued. request_id protects you from double purchases.

๐Ÿš€ Fast

Code arrives by callback the moment it comes โ€” no polling needed.

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?

  1. Open our Telegram bot โ€” it is the only way to get a key.
  2. Accept the terms, then press ๐Ÿ”‘ API in the main menu and copy your key.
  3. Top up the balance in the bot (๐Ÿ’ฐ My account โ†’ ๐Ÿ’ณ Top up) โ€” API purchases use the same balance.

Base URL

GEThttps://moonum-tg.com/

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.

GEThttps://moonum-tg.com/?action=getBalance&api_key=YOUR_API_KEY
ParameterTypeRequiredDescription
api_key StringrequiredStringYesYour API key (or the X-Api-Key header)
action StringrequiredStringYesPut: getBalance
Response
{
  "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).

GEThttps://moonum-tg.com/?action=getCountries&api_key=YOUR_API_KEY
ParameterTypeRequiredDescription
api_key StringrequiredStringYesYour API key (or the X-Api-Key header)
action StringrequiredStringYesPut: getCountries
Response
{
  "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.

GEThttps://moonum-tg.com/?action=getNumber&api_key=YOUR_API_KEY&country=BD&max_price=0.40&request_id=order-1001
ParameterTypeRequiredDescription
api_key StringrequiredStringYesYour API key (or the X-Api-Key header)
action StringrequiredStringYesPut: getNumber
country StringrequiredStringYesCountry, ISO 3166-1 alpha-2 (e.g. KE)
max_price NumberoptionalNumberNoHighest 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 StringoptionalStringNoYour 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.
Response
{
  "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.

GEThttps://moonum-tg.com/?action=getCode&api_key=YOUR_API_KEY&id=1532
ParameterTypeRequiredDescription
api_key StringrequiredStringYesYour API key (or the X-Api-Key header)
action StringrequiredStringYesPut: getCode
id IntegerrequiredIntegerYesNumber id from getNumber
Response
{"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.

GEThttps://moonum-tg.com/?action=getStatus&api_key=YOUR_API_KEY&id=1532
ParameterTypeRequiredDescription
api_key StringrequiredStringYesYour API key (or the X-Api-Key header)
action StringrequiredStringYesPut: getStatus
id IntegerrequiredIntegerYesNumber id from getNumber
Response
{
  "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.

GEThttps://moonum-tg.com/?action=setCallback&api_key=YOUR_API_KEY&url=https://example.com/hook
ParameterTypeRequiredDescription
api_key StringrequiredStringYesYour API key (or the X-Api-Key header)
action StringrequiredStringYesPut: setCallback
url StringoptionalStringNoPublic https:// URL (port 443, up to 255 chars)
Response
{"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_KEYKey missing or invalid (401)
API_BLOCKEDAPI access blocked by admin (403)
BANNEDAccount blocked (403)
MAINTENANCEService temporarily off (503)
BAD_ACTIONUnknown action (400)
BAD_COUNTRY ยท BAD_MAX_PRICE ยท BAD_REQUEST_ID ยท BAD_URLInvalid parameter (400)
NO_NUMBERSCountry not available (404)
PRICE_TOO_HIGHPrice above max_price, current price included (409)
NO_BALANCENot enough balance, price and balance included (402)
NO_NUMBER_ISSUEDProvider issued no number, nothing charged โ€” retry later (503)
IN_PROGRESSSame request_id is still being processed (409)
REQUEST_ID_USEDrequest_id already used for another action (409)
NOT_FOUNDNumber id not found (404)
RATE_LIMITToo many requests: max 300 / 10 s and 1200 / 60 s, see Retry-After (429)
DAILY_LIMITDaily request limit reached, resets tomorrow (429)
PROVIDER_ERRORCode check failed, retry (502)
INTERNALUnexpected server error โ€” check getStatus / getBalance before retrying (500)
PENDING_REVIEWRare: number reserved but not saved โ€” do not retry, contact support (500)

Important rules

๐Ÿ’ฌ Support

Questions, top-ups and partnership โ€” write to us in Telegram.