Typical flow
services&country=MY once — pick the service ID for the app you need (e.g. WhatsApp, route with the best success rate).
get_number&service=<id> — you are charged the price shown and get a number plus an order ID.
- Use the number in the app. Poll
get_status&order=<id> every 5–10 seconds until status is RECEIVED; the code is in code.
- No SMS within the wait window (default 10 minutes)? The order becomes
EXPIRED and the charge is refunded automatically. You can also cancel yourself 2 minutes after the number was issued.
balance
GET /api/v2?key=YOUR_KEY&action=balance
→ {"balance":"48.20","currency":"MYR"}
countries
Countries with at least one live route.
GET /api/v2?key=YOUR_KEY&action=countries
→ [{"code":"MY","name":"Malaysia","apps":63}, {"code":"SG","name":"Singapore","apps":41}, …]
services
| Parameter | Description |
| country | Required. Country code from countries, e.g. MY. |
Within one app the routes are ordered by success rate (best first). success_rate is a percentage or null for new routes.
GET /api/v2?key=YOUR_KEY&action=services&country=MY
→ [
{"service":"1042","country":"MY","app":"WhatsApp","app_key":"whatsapp","price":"19.40","currency":"MYR","success_rate":26},
{"service":"1050","country":"MY","app":"WhatsApp","app_key":"whatsapp","price":"17.60","currency":"MYR","success_rate":13},
{"service":"1077","country":"MY","app":"Shopee","app_key":"shopee","price":"1.80","currency":"MYR","success_rate":34},
…
]
get_number
| Parameter | Description |
| service | Required. Service ID from services. |
Charges your balance immediately. The number is valid until expires_at (UTC). If no SMS arrives by then, the order expires and the charge is refunded.
GET /api/v2?key=YOUR_KEY&action=get_number&service=1042
→ {"order":"5821","status":"WAITING","number":"60112223344","country":"MY","app":"WhatsApp",
"code":null,"text":null,"price":"19.40","currency":"MYR",
"expires_at":"2026-09-27T09:41:12Z","created_at":"2026-09-27T09:31:12Z","balance":"28.80"}
// errors: {"error":"Not enough balance. …"} {"error":"This route is under maintenance …"}
get_status
| Parameter | Description |
| order | Required. Order ID from get_number. |
| status | Meaning |
| WAITING | Number issued, no SMS yet. Keep polling (we check the provider at most once every 5 seconds). |
| RECEIVED | Code arrived — see code (digits only) and text (full message). Final. |
| EXPIRED | No SMS within the window. Refunded. Final. |
| CANCELED | You cancelled, or the number could not be issued. Refunded. Final. |
| PENDING | Being processed or checked by support. Do not request again — you will not be charged twice. |
GET /api/v2?key=YOUR_KEY&action=get_status&order=5821
→ {"order":"5821","status":"RECEIVED","number":"60112223344","country":"MY","app":"WhatsApp",
"code":"482913","text":"WhatsApp code 482-913","price":"19.40","currency":"MYR", …}
cancel
| Parameter | Description |
| order | Required. Order ID. |
Allowed 2 minutes after the number was issued and only while the status is WAITING. Refunds in full. If the code arrived in the meantime the call fails and the order stays RECEIVED.
GET /api/v2?key=YOUR_KEY&action=cancel&order=5821
→ {"order":"5821","status":"CANCELED","refunded":"19.40", …}
// too early: {"error":"A number can be cancelled 2 minutes after it was issued — 74s to go."}
Example (Python)
import requests, time
API = "https://dapatotp.com/api/v2"; KEY = "YOUR_KEY"
svc = [s for s in requests.get(API, params={"key": KEY, "action": "services", "country": "MY"}).json()
if s["app_key"] == "whatsapp"][0]
o = requests.get(API, params={"key": KEY, "action": "get_number", "service": svc["service"]}).json()
print("number:", o["number"])
while True:
time.sleep(6)
st = requests.get(API, params={"key": KEY, "action": "get_status", "order": o["order"]}).json()
if st["status"] == "RECEIVED": print("code:", st["code"]); break
if st["status"] in ("EXPIRED", "CANCELED"): print("no sms, refunded"); break