Skip to main content
100+
Countries
1000+ services. Pay with crypto, no KYC.
Buy Number

SMS Verification API — SMSNoKYC

Automate OTP verification end to end. Claim virtual numbers across 190+ countries, read SMS codes within seconds, rent dedicated long-term lines, and drive every order through one REST surface — no API key, no KYC, paid in cryptocurrency.

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

Authentication required. Every request rides a session cookie, so you must be signed in to your SMSNoKYC account. Establish a session through the web interface or the auth endpoint before calling.

Why developers choose the SMSNoKYC API

SMSNoKYC is the most flexible SMS verification API for developers who need anonymity, global coverage and predictable pricing. Unlike legacy SMS-OTP providers that gate access behind enterprise contracts, monthly minimums and KYC questionnaires, SMSNoKYC works with any HTTPS client, charges strictly per-number, and accepts 20+ cryptocurrencies including Bitcoin, Monero, Ethereum, USDT, USDC, Solana, Litecoin, XRP, TRON and Toncoin.

Typical use cases include automating account signups for scaled QA, retrieving one-time passwords for headless agents and CI bots, validating phone-required flows in continuous integration, renting dedicated long-term numbers for Telegram or WhatsApp accounts that need uninterrupted SMS reception, and powering geo-distributed verification across 190+ countries with explicit operator-tier control — virtual, physical or premium.

Authentication

The API uses cookie-based session authentication. To authenticate programmatically:

  1. Send a POST request to /auth-api.php with your seed phrase
  2. Store the session cookie from the response
  3. Include the cookie in all subsequent API requests
POST /auth-api.php

Authenticate with your seed phrase and establish a session.

ParameterTypeRequiredDescription
actionstringrequiredMust be "login"
seedstringrequiredYour 16-character access seed (e.g. 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

All API endpoints are relative to:

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

All responses are JSON. POST endpoints accept both application/json and application/x-www-form-urlencoded request bodies.

Rate Limits

The API enforces the following rate limits:

EndpointLimitWindow
Authentication5 attempts15 minutes
All other endpointsNo hard limit

Rate limiting: Authentication is limited to 5 attempts per 15 minutes. Other endpoints are not currently rate-limited, but excessive usage may be throttled. Use reasonable request intervals.

Error Handling

All errors return a JSON object with an <code>error</code> 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

Common application-level errors:

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

Returns all active countries with available virtual numbers. No authentication 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}

Returns available services for a specific country, including prices and stock. Without a country code, returns all services 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}

Returns available operators (carriers) for a specific country. Each operator has a type and a price multiplier applied to 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 numbers, cheapest, may be blocked by some services. physical — real SIM cards, higher success rate. premium — fastest delivery (~10s), highest success rate.

Buy Number (SMS Activation)

POST /api.php?action=buy

Purchase a virtual number for one-time SMS verification. The number is active for 20 minutes. If no SMS is received, your balance is automatically refunded.

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

Returns your 50 most recent orders, including phone numbers and SMS codes. Poll this endpoint to check for incoming SMS codes on active orders.

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 — waiting for SMS. completed — SMS received. cancelled — cancelled by user. refunded — auto-refunded (no SMS received before timeout). expired — timed out.

Get Rental Price

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

Get the price for renting a dedicated number from a specific operator for a given duration.

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

Rent one or more dedicated phone numbers. The number is exclusively yours for the entire rental period and receives unlimited incoming SMS.

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

Returns the current user's account information and balance. Use this to check authentication status and available funds.

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

Complete Workflow Example

Here's a full Python example that authenticates, finds a service, buys a number, and polls for the SMS code:

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")

Frequently Asked Questions

What is the SMSNoKYC verification API for?

It opens the same catalogue the site uses to your own code: virtual numbers in 190+ countries for one-time OTP verification and for 7-to-90-day rentals. Over a plain JSON REST interface you can browse apps, read live prices, claim numbers, pull incoming codes and refund failed activations — no KYC, crypto-only billing.

Is an API key or OAuth token required?

No. Auth is a session cookie: POST your 16-character access seed once to /auth-api.php, then carry the returned cookie on every later call. Nothing to provision, rotate or revoke — you sign in once per session and stay signed in for the life of that cookie.

What does the API cost?

The API is free to call — no monthly fee, no subscription, no minimum volume. You pay only per number: one-time activations from $0.05, dedicated rentals from a few dollars for 7 days. Everything draws on your prepaid balance, and any activation that never receives an SMS is refunded on its own.

Which languages and frameworks can call it?

Anything that can make an HTTPS request works — Python (requests, httpx), Node.js (fetch, axios), Go, PHP, Ruby, Java, C#, cURL from Bash and the rest. The docs include copy-paste examples in cURL, Python and JavaScript, and a full OpenAPI 3.0 file at /openapi.json lets you generate a typed client in whatever language you prefer.

What if a verification code never arrives?

Each activation runs on a 20-minute window. If nothing lands before it closes, the order cancels itself and the full price returns to your balance — no ticket, no manual retry. You can spend that refunded balance right away on another number, perhaps on a different operator tier (virtual, physical or premium) for a better hit rate.

Does the API have rate limits?

Sign-in is capped at 5 tries per 15 minutes per IP to block seed guessing. The rest — catalogue, buy, orders, rentals — has no hard cap right now, but please keep intervals sensible: polling /api.php?action=orders every 3-5 seconds is ample for reading SMS, and sustained bursts past roughly 10 req/s may be throttled at the WAF.