Beginner APIAutomationPythonNode

🔄Automated ordering and polling with an API Key

A short Python / Node script that automates the full "order a number → poll on a timer → get the code" flow, with timeout and failure-retry handling.

✍️ SimSmsBox 📅 May 25, 2026

Manual curl is fine for debugging, but real workloads need automation. This tutorial gives polling scripts you can use directly.

The idea

  1. Create an order and get the orderId plus apiBindingKey (the receive-URL credential);
  2. Poll the receive URL /api/sms/record?key=<apiBindingKey>&format=txt every 2–3 seconds (this URL stays valid for the whole rental window and needs no auth header);
  3. Return the code as soon as it responds YES|<code>;
  4. Cancel the order and retry if the max wait is exceeded.

Python example

import time, requests

BASE = "https://api.simsmsbox.com"
HEADERS = {"X-API-Key": "psk_xxxxxxxx"}

def get_code(service="telegram", country="US", timeout=180):
    r = requests.post(f"{BASE}/api/sms/orders/purchase",
                      headers=HEADERS,
                      json={"service": service, "country": country, "cardKind": "physical", "rentDays": 30})
    order = r.json()
    oid = order["orderId"]
    key = order["apiBindingKey"]                # receive-URL credential; valid for the whole rental window
    deadline = time.time() + timeout
    while time.time() < deadline:
        # Receive URL: no X-API-Key needed, the key authorizes it; format=txt returns YES|<code> or NO|
        resp = requests.get(f"{BASE}/api/sms/record",
                            params={"key": key, "format": "txt"}).text.strip()
        if resp.startswith("YES|"):
            return resp.split("|", 1)[1]
        time.sleep(3)
    # cancel on timeout (refundable if no code)
    requests.post(f"{BASE}/api/sms/orders/{oid}/cancel", headers=HEADERS)
    raise TimeoutError("code did not arrive before timeout")

print(get_code())

Node.js example

const BASE = "https://api.simsmsbox.com";
const HEADERS = { "X-API-Key": "psk_xxxxxxxx", "Content-Type": "application/json" };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

async function getCode(service = "telegram", country = "US", timeout = 180000) {
  const res = await fetch(`${BASE}/api/sms/orders/purchase`, {
    method: "POST", headers: HEADERS,
    body: JSON.stringify({ service, country, cardKind: "physical", rentDays: 30 }),
  });
  const { orderId, apiBindingKey } = await res.json();
  const deadline = Date.now() + timeout;
  while (Date.now() < deadline) {
    // Receive URL: no auth header, the key authorizes it
    const txt = await (await fetch(`${BASE}/api/sms/record?key=${apiBindingKey}&format=txt`)).text();
    if (txt.startsWith("YES|")) return txt.slice(4).trim();
    await sleep(3000);
  }
  await fetch(`${BASE}/api/sms/orders/${orderId}/cancel`, { method: "POST", headers: HEADERS });
  throw new Error("code did not arrive before timeout");
}

Best practices

ItemRecommendation
How to fetchPrefer the receive URL /api/sms/record (always valid, no auth header); GET /orders/{id} as fallback
Polling interval2–3 seconds; too frequent wastes requests
Max wait60–180 seconds, tuned per app
Failure retryCancel the old order, then re-order
ConcurrencyControl concurrency with wallet balance and quota

The receive URL stays valid for the whole order window and needs no auth header — polling it is the simplest approach; the order-query endpoint is a fallback. Further reading: Custom receive URL and templated responses.

← Back to Tutorials