Quickstart
Browse the catalogue and get a quote without a key, then create one, buy a number with a price ceiling, read the code and cancel if needed — in cURL, Node and Python.
This walks the whole path from "what can I buy?" to a verification code. The first three steps need no account and no key, so you can build and test your catalogue screens before you sign up.
- 1 · Find the platform (no key)
Platform ids are exact. List the platforms in stock and keep the id you need:
curl https://numestri.com/api/v1/catalog/platforms{ "success": 1, "prices_at": "2026-10-14T01:40:00.000Z", "count": 1326, "next": "/api/v1/catalog/platforms/{platform}/countries", "data": [ { "id": "telegram", "name": "Telegram", "countries": 14, "from_price": "0.99", "from_price_cents": 99 } ] }from_priceis the cheapest number for that platform in any country. - 2 · Pick a country (no key)
curl https://numestri.com/api/v1/catalog/platforms/telegram/countries{ "success": 1, "prices_at": "2026-10-14T01:40:00.000Z", "platform": "telegram", "count": 14, "next": "/api/v1/catalog/platforms/telegram/countries/{country}/providers", "data": [ { "id": "US", "name": "United States", "providers": 3, "from_price": "0.99", "from_price_cents": 99 } ] }Want to choose a specific provider or offer? Go two levels deeper — see the catalogue tree. Otherwise the best option is picked for you.
- 3 · Get a quote (no key)
/request/pricesays what an order would cost right now, and which option would fill it:curl "https://numestri.com/api/v1/request/price?service=telegram&country=US"{ "success": 1, "service": { "id": "telegram", "name": "Telegram" }, "country": { "id": "US", "name": "United States" }, "price": "0.99", "price_cents": 99, "high_price": "1.30", "option": "5sQY4PwqkxD3gE7O", "options": [ … ], "shared_inbox": null }These are public list prices. Once you have a key, send it here too and you see your account's own prices — the ones you will actually be charged. See Quotes.
- 4 · Create a key and add balance
Sign up, open Developer in the dashboard (
/dashboard/developer) and choose New key. Copy it — it is shown once. Top up from Deposit.Keep the key on your server, for example in an environment variable, and check it works:
export NUMESTRI_KEY="…" curl https://numestri.com/api/v1/request/balance -H "Authorization: Bearer $NUMESTRI_KEY"{ "balance": "10.00" }A
403here means the key is wrong; see Authentication. - 5 · Order the number
Send the platform and country. Add
max_priceso the order is refused, at no cost, if the price has risen above what you are willing to pay, and anIdempotency-Keyso a retried request can never buy twice.- cURL
- Node
- Python
curl https://numestri.com/api/v1/purchase/sms \ -H "Authorization: Bearer $NUMESTRI_KEY" \ -H "Idempotency-Key: 7d0f3b8e-4a51-4c1e-9b0a-2f6c1d9e8a31" \ -d service=telegram -d country=US -d max_price=1.00const res = await fetch("https://numestri.com/api/v1/purchase/sms", { method: "POST", headers: { Authorization: `Bearer ${process.env.NUMESTRI_KEY}`, "Idempotency-Key": crypto.randomUUID(), }, body: new URLSearchParams({ service: "telegram", country: "US", max_price: "1.00" }), }); const order = await res.json(); if (!order.success) throw new Error(`${order.code ?? res.status}: ${order.message ?? order.errors?.[0]?.message}`); console.log(order.phonenumber, order.order_id);import os, uuid, requests order = requests.post( "https://numestri.com/api/v1/purchase/sms", headers={ "Authorization": f"Bearer {os.environ['NUMESTRI_KEY']}", "Idempotency-Key": str(uuid.uuid4()), }, data={"service": "telegram", "country": "US", "max_price": "1.00"}, ).json() print(order["phonenumber"], order["order_id"]){ "success": 1, "number": 12025550123, "cc": "1", "phonenumber": "2025550123", "order_id": "JRJ5UEXS", "country": "United States", "country_code": "US", "service": "Telegram", "service_id": "telegram", "expires_in": 1198, "expiration": 1792131600, "cost": "0.99", "cost_in_cents": 99 }costis what was taken from your balance. It is worked out on our side at the moment of the order — you never send a price — and it is never above yourmax_price. If it would be, the answer is400with codePRICE_ABOVE_MAXand nothing is charged.Use the number on the platform you are verifying with, and keep
order_id. - 6 · Wait for the code
Poll every few seconds until
statusis3, or skip polling entirely with a webhook.curl https://numestri.com/api/v1/sms/check -H "Authorization: Bearer $NUMESTRI_KEY" -d orderid=JRJ5UEXS- Waiting
- Code arrived
{ "status": 1, "resend": 0, "time_left": 1188 }{ "status": 3, "sms": "140722", "full_sms": "140722 is your Telegram verification code." }Stop polling on
3(code), or on2,5or6(expired, cancelled, refunded). The full list is in Receiving the code. - 7 · Cancel, or let it refund itself
Changed your mind, or the platform never sent the SMS? Cancel any time before a code arrives for a full refund:
curl https://numestri.com/api/v1/sms/cancel -H "Authorization: Bearer $NUMESTRI_KEY" -d orderid=JRJ5UEXS{ "success": 1, "message": "The order has been cancelled, and you have been refunded 0.99 dollars." }If you do nothing and no code arrives before the number expires, the full price is returned automatically. A number that did receive a code is not refundable. See Cancel, resend and refunds.
The whole loop in one script
const api = "https://numestri.com/api/v1";
const auth = { Authorization: `Bearer ${process.env.NUMESTRI_KEY}` };
const call = (path, params, headers = {}) =>
fetch(`${api}${path}`, { method: "POST", headers: { ...auth, ...headers }, body: new URLSearchParams(params) })
.then((r) => r.json());
// Public: what would it cost? (Sent with the key, so these are your prices.)
const quote = await call("/request/price", { service: "telegram", country: "US" });
if (!quote.success) throw new Error(quote.message ?? quote.errors[0].message);
// Keyed: buy it, capped at the quoted price.
const order = await call(
"/purchase/sms",
{ service: "telegram", country: "US", max_price: quote.price },
{ "Idempotency-Key": crypto.randomUUID() },
);
if (!order.success) throw new Error(`${order.code}: ${order.message}`);
console.log("Use this number:", order.number);
// Wait up to two minutes for the code, then cancel.
for (let i = 0; i < 30; i++) {
await new Promise((r) => setTimeout(r, 4000));
const check = await call("/sms/check", { orderid: order.order_id });
if (check.status === 3) { console.log("code:", check.sms); process.exit(0); }
if ([2, 5, 6].includes(check.status)) throw new Error("No code; the order was refunded.");
}
console.log(await call("/sms/cancel", { orderid: order.order_id }));Capping at quote.price means the order goes through only if the price has not moved since the quote. To allow a little movement, cap a few cents higher.