Home / OTP Gateway
OTP Gateway & Receive API

Temporary verification numbers, captured by API

Order a number for a specific service and country, receive the one-time password as a signed webhook or by polling, and get a full automatic refund if no SMS ever arrives.

From $0.20 per code20-minute activation windowPay only if the code arrives
GET /api/v1/activations/act_9f2c…
{
  "id": "act_9f2c41d0b7e3a6158c24",
  "object": "activation",
  "status": "received",
  "service": "telegram",
  "country": "us",
  "phone_number": "+15550142231",
  "code": "482913",
  "sms_text": "Telegram code: 482913",
  "price": 0.2,
  "created_at": 1793318400,
  "expires_at": 1793319600,
  "received_at": 1793318447
}
Activation lifecycle

Every activation ends in a code or a refund

An activation is a single-use reservation of a number for one service. Its status moves through a small, well-defined state machine.

Happy path
pendingNumber issued, waiting for SMS
→
receivedCode parsed and delivered
→
completedYou confirm and close it
No SMS
pendingWindow of ~20 minutes
→
expiredWindow closed, no SMS
or
cancelledYou cancel after the cooldown
→
refundedFull amount back to wallet

Debit on order

The current price for the service and country is debited when the activation is created. If the order fails upstream, it is refunded immediately.

Retry codes

If the service sends another SMS while the activation is received, the code is updated so you always read the latest one.

Explicit completion

Call POST /v1/activations/{id}/complete once you have used the code. Only activations that received a code can be completed.

Delivery modes

Polling or webhooks — your choice

Both modes read from the same activation record. Many teams start by polling and move to webhooks in production.

PollingWebhooks
How it worksCall GET /v1/activations/{id} until status changesWe POST activation.sms_received to your HTTPS endpoint
LatencyBounded by your poll intervalPushed as soon as the code is captured
Rate-limit usageEach poll counts toward your 300 requests/minDeliveries do not count toward your API limit
InfrastructureNone — works from scripts, CI jobs and notebooksA publicly reachable HTTPS endpoint
SecurityBearer API key over TLSHMAC-SHA256 signature with timestamp per delivery
Lifecycle eventsRead status on each callactivation.sms_received, activation.expired, activation.cancelled
Best forPrototypes, CI jobs, low volumeProduction systems and higher volume

Guides: Webhook-based OTP capture · Measuring OTP delivery latency · Developer console

Code sample

Order, wait, read the code

A complete polling loop in Python. Swap the loop for a webhook handler when you are ready — the activation object is identical.

  • max_price rejects the order with 409 if the live price is higher
  • 402 tells you to top up before retrying
  • Cancel with POST /v1/activations/{id}/cancel after the short cooldown

Full integration guide →

poll_otp.py
import time, requests

API = "https://otproute.com/api/v1"
H = {"Authorization": "Bearer or_live_…"}

act = requests.post(f"{API}/activations", headers=H,
    json={"service": "telegram", "country": "us", "max_price": 0.50}).json()
# use act["phone_number"] in the flow under test

while True:
    a = requests.get(f"{API}/activations/{act['id']}", headers=H).json()
    if a["status"] == "received":
        print("OTP:", a["code"])
        requests.post(f"{API}/activations/{a['id']}/complete", headers=H)
        break
    if a["status"] in ("expired", "cancelled"):
        break  # refunded automatically
    time.sleep(5)
Pricing model

From $0.20 per code — only if it arrives

Pay as you go from your USD wallet, with no plans and no monthly fee. If no code arrives within the 20-minute window, the full amount goes back to your wallet automatically.

📊

Live cost

Each service and country has its own price, driven by live availability. See it in the dashboard or query it any time with GET /api/v1/prices.

↩️

Pay only for codes

The price is held from your wallet when you order. No code within 20 minutes, or you cancel? The full amount is returned automatically.

🛑

Price ceiling

Pass max_price to cap what a single activation may cost. Orders above it are rejected instead of debited.

See pricing

Refund rules

Refunds are automatic, not negotiated

  • Expired: no SMS within the activation window — the full price returns to your wallet.
  • Cancelled: you cancel a pending activation after the provider cooldown — full refund.
  • Failed to order: the upstream route could not issue a number — refunded immediately.
  • Received: once a code is delivered, the activation is consumed and not refundable.

Each activation is refunded at most once and recorded in your wallet ledger. See the Refund Policy.

Error codes

Errors you should handle

HTTPCodeMeaning
401unauthorizedMissing or invalid API key.
402insufficient_balanceWallet cannot cover the current price. Top up and retry.
404not_foundService unavailable in that country right now, or unknown activation ID.
409conflictPrice exceeds max_price, the activation is already closed, or the cancel cooldown has not elapsed.
423account_lockedThe account is locked. Contact support.
429rate_limitedMore than 300 requests per minute. Honour Retry-After.
{ "error": { "code": "insufficient_balance",
             "message": "Insufficient balance: this activation costs $0.20" } }
FAQ

OTP Gateway questions

How long does an activation stay open?
Roughly 20 minutes from creation. The exact deadline is returned as expires_at on the activation. If no SMS arrives by then, the activation becomes expired and is refunded in full.
Can I cancel an activation straight away?
Cancellation is allowed after a short provider cooldown, exposed as cancelable_after. Cancelling earlier returns 409 with the remaining seconds. A cancelled activation that never received a code is fully refunded.
Why does the price differ between services and countries?
Prices start from $0.20 per code and depend on live availability for each service and country route. The dashboard shows the current price before you order; use GET /api/v1/prices to read current prices and max_price to cap them per order.
Do I need webhooks?
No. Polling GET /v1/activations/{id} works everywhere. Webhooks deliver codes faster and save API requests, so they are recommended for production workloads.
Can I test without spending money?
Yes. Sandbox accounts receive simulated numbers and codes with no wallet spend. Email [email protected] to enable sandbox mode on a development account.

Capture your first OTP today

Pay as you go with no monthly fee. Pay only for activations that deliver a code.