—
Dashboard

DapatOTP API v2

https://dapatotp.com/api/v2
GET or POST (form or JSON body)
Send your API key as the key parameter on every request. Get it from Dashboard → Account.

Errors always come back as HTTP 200 with an {"error": "..."} body. Check for the error key, not the status code. Money amounts are strings in MYR. Service IDs are DapatOTP IDs and are stable across syncs.

Typical flow

  1. services&country=MY once — pick the service ID for the app you need (e.g. WhatsApp, route with the best success rate).
  2. get_number&service=<id> — you are charged the price shown and get a number plus an order ID.
  3. Use the number in the app. Poll get_status&order=<id> every 5–10 seconds until status is RECEIVED; the code is in code.
  4. 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

ParameterDescription
countryRequired. 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

ParameterDescription
serviceRequired. 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

ParameterDescription
orderRequired. Order ID from get_number.
statusMeaning
WAITINGNumber issued, no SMS yet. Keep polling (we check the provider at most once every 5 seconds).
RECEIVEDCode arrived — see code (digits only) and text (full message). Final.
EXPIREDNo SMS within the window. Refunded. Final.
CANCELEDYou cancelled, or the number could not be issued. Refunded. Final.
PENDINGBeing 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

ParameterDescription
orderRequired. 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