Manual curl is fine for debugging, but real workloads need automation. This tutorial gives polling scripts you can use directly.
The idea
- Create an order and get the
orderIdplusapiBindingKey(the receive-URL credential); - Poll the receive URL
/api/sms/record?key=<apiBindingKey>&format=txtevery 2–3 seconds (this URL stays valid for the whole rental window and needs no auth header); - Return the code as soon as it responds
YES|<code>; - 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
| Item | Recommendation |
|---|---|
| How to fetch | Prefer the receive URL /api/sms/record (always valid, no auth header); GET /orders/{id} as fallback |
| Polling interval | 2–3 seconds; too frequent wastes requests |
| Max wait | 60–180 seconds, tuned per app |
| Failure retry | Cancel the old order, then re-order |
| Concurrency | Control 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.