{"openapi":"3.1.0","info":{"title":"NanSMS API","version":"1.0.0","description":"Buy virtual phone numbers to receive SMS verification codes (Telegram, WhatsApp, Google, OpenAI...) with crypto (XNO, BTC, USDT, USDC, NANUSD and more). No account needed. Flow: GET /catalog -> GET /services/{slug} -> POST /buy -> pay payinAmount of payinCurrency to payinAddress (or open paymentLink) -> poll GET /order with the returned token until status is active -> use phone on the target service -> poll GET /order until sms[] has the code. If no SMS arrives before expiresAt (or after POST /order/cancel), the price is refunded to the balance (balanceToken)."},"servers":[{"url":"https://api.nansms.com"}],"components":{"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"securitySchemes":{"orderToken":{"type":"http","scheme":"bearer","description":"The token (ns_...) returned once by POST /buy. It is the only way to access the order."},"balanceToken":{"type":"http","scheme":"bearer","description":"Balance key nb_... returned once by POST /buy or POST /balance/topup when a balance is created. Store credit shared by all Nan services, not withdrawable."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}}},"Payment":{"type":"object","properties":{"kind":{"type":"string","enum":["buy","topup"]},"status":{"type":"string","enum":["waiting","paid","fulfilling","fulfilled","fulfill-error","failed"]},"priceUsd":{"type":"number"},"invoiceUsd":{"type":"number","description":"Amount invoiced; above priceUsd when raised to the coin minimum"},"creditUsd":{"type":"number","description":"Part of invoiceUsd credited to the balance once paid"},"paymentLink":{"type":"string"},"payinCurrency":{"type":"string"},"payinAddress":{"type":"string"},"payinAmount":{"type":"number"},"expireAt":{"type":"string","format":"date-time"},"depositDetectedAt":{"type":["string","null"],"format":"date-time"}}},"Order":{"type":"object","properties":{"orderId":{"type":"string"},"status":{"type":"string","enum":["awaiting-payment","active","received","finished","refunded","cancelled","error"],"description":"active: number ready, waiting for SMS. received: at least one SMS (more can arrive until expiresAt). refunded: no SMS or no number, price credited to the balance. cancelled: invoice expired unpaid."},"service":{"type":"string"},"serviceName":{"type":"string"},"country":{"type":"string"},"countryName":{"type":"string"},"priceUsd":{"type":"number"},"phone":{"type":["string","null"],"description":"Number in international format, e.g. +12025550123"},"expiresAt":{"type":["string","null"],"format":"date-time","description":"The number stops receiving SMS"},"cancelableAt":{"type":["string","null"],"format":"date-time","description":"POST /order/cancel is refused before this time (some numbers need a short wait, usually 2-5 minutes). null: can be cancelled at any time"},"sms":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"text":{"type":"string"},"sender":{"type":"string"},"receivedAt":{"type":"string","format":"date-time"}}}},"refundReason":{"type":"string"},"payments":{"type":"array","items":{"$ref":"#/components/schemas/Payment"}},"serverTime":{"type":"string","format":"date-time"}}}}},"paths":{"/catalog":{"get":{"summary":"All services with their lowest price, popular services, accepted coins","responses":{"200":{"description":"services[] {slug, name, fromPriceUsd, countries}, popular[], payinCurrencies[] {ticker, name, feeless, minUsd}, topup limits"}}}},"/services/{slug}":{"get":{"summary":"Countries where a service number is available, best delivery rate first","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string"},"example":"telegram"}],"responses":{"200":{"description":"countries[] {country, iso, name, prefix, priceUsd, count, rate}. rate: delivery success % over the last week (null = not enough data)"},"400":{"$ref":"#/components/responses/Error"}}}},"/price":{"get":{"summary":"Price of one number","parameters":[{"name":"service","in":"query","required":true,"schema":{"type":"string"},"example":"telegram"},{"name":"country","in":"query","required":true,"schema":{"type":"string"},"example":"usa"}],"responses":{"200":{"description":"{ priceUsd, available, rate }"}}}},"/buy":{"post":{"summary":"Order a number","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["service","country"],"properties":{"service":{"type":"string","example":"telegram"},"country":{"type":"string","example":"usa"},"payinCurrency":{"type":"string","description":"Ticker from GET /payin-currencies (XNO, BTC, USDT-TRX...), BALANCE to pay from the balance instantly, or omit to choose on the Nanswap Pay page","example":"XNO"},"balanceToken":{"type":"string","description":"Existing balance (nb_...): refunds and coin-minimum surplus land there; required with BALANCE"}}}}}},"responses":{"201":{"description":"{ token, orderId, orderUrl, priceUsd, payment, balanceToken? }. token is shown once. balanceToken only when a new balance was created: keep it, refunds go there."},"400":{"$ref":"#/components/responses/Error"},"402":{"description":"Insufficient balance"},"409":{"description":"No number available in this country right now"},"429":{"description":"Too many orders"},"503":{"description":"Temporarily unavailable"}}}},"/order":{"get":{"summary":"Order status, number and received SMS","security":[{"orderToken":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"401":{"$ref":"#/components/responses/Error"}}}},"/order/stream":{"get":{"summary":"Live order updates (Server-Sent Events, event: order, data: Order JSON)","security":[{"orderToken":[]}],"responses":{"200":{"description":"text/event-stream"}}}},"/order/cancel":{"post":{"summary":"Cancel a number that has not received any SMS yet; the price is refunded to the balance. Refused (409) before cancelableAt","security":[{"orderToken":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"409":{"$ref":"#/components/responses/Error"}}}},"/order/finish":{"post":{"summary":"Done with the number after receiving the code (releases it)","security":[{"orderToken":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"409":{"$ref":"#/components/responses/Error"}}}},"/payin-currencies":{"get":{"summary":"Coins accepted as payinCurrency","responses":{"200":{"description":"{ featured[], all[] }"}}}},"/balance":{"get":{"summary":"Balance amount and recent movements (top-ups, purchases, refunds)","security":[{"balanceToken":[]}],"responses":{"200":{"description":"{ balanceUsd, transactions[] }"},"401":{"$ref":"#/components/responses/Error"}}}},"/balance/topup":{"post":{"summary":"Prefund the balance with a crypto invoice","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["amountUsd"],"properties":{"amountUsd":{"type":"number","minimum":1,"maximum":1000},"payinCurrency":{"type":"string","example":"XNO"},"balanceToken":{"type":"string","description":"Omit to create a new balance (key returned once)"}}}}}},"responses":{"201":{"description":"{ topupId, payment, balanceToken? }"},"400":{"description":"Invalid amount or below the coin minimum (minUsd)"}}}},"/balance/topup/{id}":{"get":{"summary":"Top-up status","security":[{"balanceToken":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ payment, balanceUsd }"}}}}}}