Skip to main content
116
Countries
133 services, 400 carrier routes, 15,400+ live price points. Crypto only, zero identity checks.
Rent a Number

SmsNoKYC for Developers: SMS Verification You Can Script

Script the entire verification loop through one JSON interface. 116 countries, 133 services, 400 carrier routes and 15,400+ live prices sit behind a handful of endpoints: allocate a number, catch its incoming code, hold a rental for up to 90 days, settle in crypto. No API key exists here — a seed phrase is the only credential you will ever present.

Reading time: 5 min REST · JSON · OpenAPI 3.0 OpenAPI spec →

Authentication required. Sessions ride on cookies. Sign in with your seed phrase — through the site or directly against the auth endpoint documented below — and every subsequent request inherits that session on its own.

Made for scripts, pipelines and autonomous agents

Legacy OTP vendors want contracts signed, compliance cleared and monthly minimums committed before your first request goes out. SmsNoKYC flips the order: hold a seed phrase, load a balance from $25 in any of 8 cryptocurrencies — Bitcoin, Monero, Ethereum, Litecoin, TRON, USDT and SOL among them — and start calling from whatever HTTPS client you already run. Billing is metered per number from $0.01, across 15,400+ live price points.

Day to day, the endpoints verify signup flows inside CI, feed OTP codes to headless browsers and scraper fleets, keep Telegram or WhatsApp accounts alive on dedicated 7 to 90 day rentals, and spread verification over 116 countries with explicit control of 400 carrier routes in three tiers — virtual, physical, premium. AI agents reach the same catalog through a native MCP server, covered on the agents page, so a tool-using model can buy numbers and read codes with no custom glue.

Authentication

Sessions are cookie-based — there is no bearer key to mint or rotate. Programmatic login takes three moves:

  1. POST your seed phrase to /auth-api.php
  2. Capture the cookie set on the response
  3. Attach that cookie to every call that follows
POST /auth-api.php

Trades your seed phrase for a live session.

ParameterTypeRequiredDescription
actionstringrequiredMust be "login"
seedstringrequiredThe 16-character seed tied to your account (format AbC3-dEf4-gHj5-kLm6)
cURL
Python
JavaScript
# Login and save session cookie curl -X POST https://smsnokyc.com/auth-api.php \ -d "action=login&seed=AbC3-dEf4-gHj5-kLm6" \ -c cookies.txt
import requests session = requests.Session() resp = session.post("https://smsnokyc.com/auth-api.php", data={ "action": "login", "seed": "AbC3-dEf4-gHj5-kLm6" }) data = resp.json() print(data) # {"success": true, "user": {...}} # session object now holds the cookie for all future requests
const resp = await fetch("https://smsnokyc.com/auth-api.php", { method: "POST", credentials: "include", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: "action=login&seed=AbC3-dEf4-gHj5-kLm6" }); const data = await resp.json(); console.log(data); // {success: true, user: {...}}
Success Response
{ "success": true, "user": { "id": 42, "prefix": "AbC3", "balance": "74.50" } }
Error Response
{ "success": false, "error": "Invalid seed." }

Base URL

Every endpoint hangs off one URL pattern:

https://smsnokyc.com/api.php?action={action}

Responses arrive as JSON in every case. POST bodies may be sent as either application/json or application/x-www-form-urlencoded.

Rate Limits

Two rules govern request volume:

EndpointLimitWindow
Authentication5 attempts15 minutes
All other endpointsNo hard limit—

Rate limiting: login accepts 5 attempts per 15 minutes; every other endpoint currently has no fixed ceiling, though sustained abuse can be slowed upstream. Space your calls sensibly.

Error Handling

Every failure comes back as a JSON object carrying an error field:

{ "error": "Description of what went wrong" }
HTTP CodeMeaning
200Success (check response body for application-level errors)
403Invalid CSRF token
405Wrong HTTP method (e.g. GET on a POST-only endpoint)
429Rate limit exceeded

Application-level errors you will meet most often:

ErrorCause
"Login required"Session expired or not authenticated
"Insufficient balance"Not enough funds — includes need and have fields
"Service not available for this country"No stock or service inactive for the selected country
"Missing country or service"Required parameters were not provided

List Countries

GET /api.php?action=countries

Lists every country currently holding stock — 116 at last count. Open endpoint, no session required.

cURL
Python
JavaScript
curl https://smsnokyc.com/api.php?action=countries
resp = session.get("https://smsnokyc.com/api.php", params={"action": "countries"}) countries = resp.json() for c in countries: print(c["code"], c["name"])
const resp = await fetch("https://smsnokyc.com/api.php?action=countries"); const countries = await resp.json();
Response
[ { "id": 1, "code": "us", "name": "USA" }, { "id": 2, "code": "gb", "name": "UK" }, { "id": 3, "code": "de", "name": "Germany" } ]

List Services

GET /api.php?action=services&country={code}

Pulls the service sheet for one country, live price and stock included. Leave the country parameter off to receive the full 133-service catalog without pricing.

ParameterTypeRequiredDescription
countrystringoptionalISO 3166-1 alpha-2 country code (e.g. us, gb, de)
Response (with country)
[ { "id": 12, "name": "WhatsApp", "slug": "whatsapp", "icon_code": "WA", "icon_color": "#25d366", "category": "social", "price": "0.35", "stock": 847 } ]

List Operators

GET /api.php?action=operators&country={code}

Enumerates the carrier routes behind a country. Each operator carries a tier plus a multiplier applied on top of the base service price.

ParameterTypeRequiredDescription
countrystringrequiredISO 3166-1 alpha-2 country code
Response
[ { "id": 5, "name": "T-Mobile", "type": "physical", "price_multiplier": "1.50", "icon_slug": "tmobile", "icon_domain": "t-mobile.com" } ]

Operator types: virtual — VoIP-backed, lowest cost, occasionally rejected by strict platforms. physical — genuine SIM hardware, stronger acceptance. premium — highest acceptance and the quickest delivery, around 10 seconds.

Buy Number (SMS Activation)

POST /api.php?action=buy

Reserves a number for a single verification. It stays yours for 20 minutes; if no message shows up inside that window, the charge flows back to your balance automatically.

ParameterTypeRequiredDescription
countrystringrequiredCountry code (e.g. us)
service_idintegerrequiredService ID from List Services
operator_idintegeroptionalOperator ID from List Operators. Omit for default operator.
cURL
Python
JavaScript
curl -X POST https://smsnokyc.com/api.php?action=buy \ -b cookies.txt \ -H "Content-Type: application/json" \ -d '{"country":"us","service_id":12,"operator_id":5}'
resp = session.post("https://smsnokyc.com/api.php?action=buy", json={ "country": "us", "service_id": 12, "operator_id": 5 }) order = resp.json() print(f"Order #{order['order_id']} — ${order['price']}")
const resp = await fetch("https://smsnokyc.com/api.php?action=buy", { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ country: "us", service_id: 12, operator_id: 5 }) }); const order = await resp.json();
Success Response
{ "success": true, "order_id": 1847, "price": 0.53, "balance": "73.97" }
Error: Insufficient Balance
{ "error": "Insufficient balance", "need": 0.53, "have": "0.10" }

List Orders

GET /api.php?action=orders

Serves your latest 50 orders with their numbers and any captured codes. Poll here while an activation is waiting on its SMS.

Response
[ { "id": 1847, "price": "0.53", "status": "completed", "phone_number": "+12025551234", "sms_code": "847293", "created_at": "2026-04-09 14:32:00", "country_code": "us", "country_name": "USA", "service_name": "WhatsApp", "operator_name": "T-Mobile" } ]

Order statuses: active — still listening for a message. completed — code captured. cancelled — closed by you. refunded — credited back automatically after a silent timeout. expired — window elapsed.

Get Rental Price

GET /api.php?action=rental_price&country={code}&operator_id={id}&duration={days}

Quotes the cost of holding a dedicated number on a given operator for a chosen term.

ParameterTypeRequiredDescription
countrystringrequiredCountry code
operator_idintegerrequiredOperator ID
durationintegerrequiredRental duration in days: 7, 14, 30, or 90
Response
{ "price": "12.50", "duration": 30, "operator": "T-Mobile", "type": "physical", "country": "USA" }

Rent Number

POST /api.php?action=rental_buy

Locks in one or more dedicated numbers. Each stays exclusively yours for the whole term — 7 to 90 days — and accepts unlimited inbound SMS from any service.

ParameterTypeRequiredDescription
countrystringrequiredCountry code
operator_idintegerrequiredOperator ID
durationintegerrequired7, 14, 30, or 90 days
qtyintegeroptionalNumber of numbers to rent (1–10, default: 1)
Success Response
{ "success": true, "order_ids": [1848, 1849], "total": 25.00, "qty": 2, "unit_price": 12.50, "duration": 30, "balance": "49.50" }

Get User Info

GET /api.php?action=user

Reports the account behind the current session, balance included. One call doubles as a login check and a funds check.

Authenticated
{ "logged_in": true, "id": 42, "prefix": "AbC3", "balance": "74.50" }
Not Authenticated
{ "logged_in": false }

End-to-End Script

The script below runs the whole loop in Python — session, catalog lookup, purchase, then polling until the code drops:

Python
import requests, time BASE = "https://smsnokyc.com" SEED = "AbC3-dEf4-gHj5-kLm6" s = requests.Session() # 1. Authenticate s.post(f"{BASE}/auth-api.php", data={"action": "login", "seed": SEED}) # 2. Check balance user = s.get(f"{BASE}/api.php?action=user").json() print(f"Balance: ${user['balance']}") # 3. Get services for USA services = s.get(f"{BASE}/api.php?action=services&country=us").json() whatsapp = next(svc for svc in services if svc["name"] == "WhatsApp") print(f"WhatsApp: ${whatsapp['price']} ({whatsapp['stock']} in stock)") # 4. Buy a number order = s.post(f"{BASE}/api.php?action=buy", json={ "country": "us", "service_id": whatsapp["id"] }).json() print(f"Order #{order['order_id']} created") # 5. Poll for SMS code for _ in range(60): orders = s.get(f"{BASE}/api.php?action=orders").json() my_order = next(o for o in orders if o["id"] == order["order_id"]) if my_order["sms_code"]: print(f"SMS code: {my_order['sms_code']}") print(f"Phone: {my_order['phone_number']}") break print("Waiting for SMS...") time.sleep(5) else: print("Timeout — balance will be refunded automatically")

Developer Questions, Answered

Which operations does the SmsNoKYC developer API expose?

Everything the dashboard does, a script can do: pull the catalog of 116 countries and 133 services, inspect 15,400+ live price points spread over 400 carrier routes, allocate a number for a one-time OTP, read the incoming code the moment it lands, hold a dedicated rental for 7, 14, 30 or 90 days, and audit every order. All of it is plain JSON over HTTPS, billed in crypto, with no identity step anywhere in the flow.

Is there an API key to generate before my first request?

Nothing to generate, nothing to rotate. Your seed phrase is the credential itself: POST it once to /auth-api.php, keep the session cookie the server returns, and send that cookie with each later call. No key dashboard, no OAuth handshake, no expiry calendar — one seed opens one session, and that is the whole model.

What does access to the API itself cost?

Access costs nothing — no monthly fee, no tier, no minimum call volume. You pay per number only: one-shot verification codes start at $0.01 and typically land between $0.20 and $1, while dedicated rentals open at $4.20 for a 7-day term. Balances are funded with 8 cryptocurrencies (minimum top-up $25), and an activation that never receives its SMS refunds itself without any action on your side.

Can I integrate from any language — or from an AI agent?

Anything that speaks HTTPS qualifies: Python, Node.js, Go, Rust, PHP, Ruby, Java, C#, or bare cURL inside a shell script. The reference ships runnable snippets in cURL, Python and JavaScript, and /openapi.json exposes a complete OpenAPI 3.0 document for generating typed clients. Autonomous agents are covered natively as well — a dedicated MCP server lets tool-using models buy numbers and collect codes on their own; the /agents page walks through the setup.

What happens when a purchased number stays silent?

You lose nothing. Every activation runs a 20-minute receive window; when it closes without a message, the platform cancels the order by itself and pushes the full charge back to your balance. No ticket, no form, no waiting on support. Buy again right away — moving up to a physical or premium operator tier usually raises the delivery rate.

How hard can I poll before throttling kicks in?

Only login carries a hard ceiling: 5 attempts per 15 minutes per IP, there to stop seed guessing. Catalog, purchase, order and rental endpoints have no fixed quota right now. Keep the cadence sane — checking the orders endpoint every 3 to 5 seconds catches every code — and hold sustained traffic under roughly 10 requests per second, since heavier bursts can be slowed at the edge layer.

Ship it

Grab a seed on the homepage, load $25 or more in crypto, and your first verification code is five requests away. Building on an LLM instead of a script? Point your model at the SmsNoKYC MCP server or follow the AI agent integration guide — the full catalog of 116 countries and 133 services becomes a tool call.

Anything the reference leaves open is covered in the help center, the SMS glossary decodes the jargon, and live activity shows the network in motion. Support runs on in-app tickets once you are signed in.