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.

Embed
Preview of the card
<a href="https://numestri.com/docs/quickstart"><img src="https://numestri.com/docs/_api/public/orgs/25229885-9620-4c08-bd2e-a0d0d74ac8b6/spaces/ef21e0c3-966d-4b03-b6d2-e66d449835d4/pages/c4e87425-6f9a-4aef-9c0b-8017cb7e5e30/social-card.svg?v=3e7ae33eec8b" alt="Quickstart" width="600" height="315"></a>

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. 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_price is the cheapest number for that platform in any country.

  2. 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. 3 · Get a quote (no key)

    /request/price says 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. 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 403 here means the key is wrong; see Authentication.

  5. 5 · Order the number

    Send the platform and country. Add max_price so the order is refused, at no cost, if the price has risen above what you are willing to pay, and an Idempotency-Key so a retried request can never buy twice.

    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.00
    {
      "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
    }

    cost is 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 your max_price. If it would be, the answer is 400 with code PRICE_ABOVE_MAX and nothing is charged.

    Use the number on the platform you are verifying with, and keep order_id.

  6. 6 · Wait for the code

    Poll every few seconds until status is 3, or skip polling entirely with a webhook.

    curl https://numestri.com/api/v1/sms/check -H "Authorization: Bearer $NUMESTRI_KEY" -d orderid=JRJ5UEXS
    { "status": 1, "resend": 0, "time_left": 1188 }

    Stop polling on 3 (code), or on 2, 5 or 6 (expired, cancelled, refunded). The full list is in Receiving the code.

  7. 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.

Next

Updated