AdaOTP API
REST API for virtual phone numbers (SMS OTP), social media services (SMM), Gmail accounts, email rental and ready-made WhatsApp numbers. All products share one balance.
v1.1.0
REST · JSON
Base URL https://api.adaotp.com/api/v1
Machine-readable versions of this page: OpenAPI 3.0 spec (import into Postman, Insomnia or an SDK generator) and llms.txt (plain Markdown for AI assistants).
All endpoints
Authentication
Every request needs your API key. Find it in Dashboard → Profile → API. Send it as the X-API-Key header (recommended), Authorization: Bearer <key>, or the apikey query parameter. Keep the key secret; if it leaks, contact support and we will rotate it.
curl 'https://api.adaotp.com/api/v1/balance' -H 'X-API-Key: YOUR_API_KEY'
Conventions
- Base URL:
https://api.adaotp.com/api/v1. Request bodies may be JSON (Content-Type: application/json) or form-encoded; file uploads usemultipart/form-data. - Every response is JSON with
success(boolean),messageanddata. Always checksuccessbefore readingdata. - Errors also carry a machine-readable
error_code(see Error codes) and arequest_id. Branch onerror_code, not onmessage— message text may change. - Amounts are integers in Indonesian Rupiah (IDR). Timestamps are ISO 8601 or
Y-m-d H:i:sin Asia/Jakarta (UTC+7). - Rate limit: 360 requests per minute per API key. Watch the
X-RateLimit-Remainingheader; HTTP 429 means wait and retry. - Idempotency: purchase endpoints accept an optional
Idempotency-Keyheader (8–128 chars). Retrying with the same key within 24 h returns the first result instead of buying twice — use a fresh UUID per purchase. - Every response has an
X-Request-Idheader. Include it when contacting support.
Quick start: receive an SMS code
- Check your balance —
GET /balance - Find the service id (e.g. WhatsApp) —
GET /services - List countries & prices for that service; pick an entry
id—GET /services/{service_id}/countries - Buy a number —
POST /orders - Poll every 5–10 s until
latest_codeis filled —GET /orders/{order_uuid} - Finish the order when done, or cancel it for a refund if no SMS arrives —
POST /orders/{order_uuid}/finish
Python
import time, uuid, requests
BASE = "https://api.adaotp.com/api/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY"}
# 1. Buy a number (Idempotency-Key makes retries safe)
r = requests.post(f"{BASE}/orders",
headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
json={"service_id": 1276, "country": 184809}).json()
if not r["success"]:
raise SystemExit(f"{r['error_code']}: {r['message']}")
order_id = r["order"]["order_uuid"]
print("Number:", r["order"]["number"])
# 2. Poll for the code
for _ in range(120):
o = requests.get(f"{BASE}/orders/{order_id}", headers=HEADERS).json()["data"]
if o["latest_code"]:
print("OTP:", o["latest_code"])
requests.post(f"{BASE}/orders/{order_id}/finish", headers=HEADERS)
break
time.sleep(5)
else:
requests.post(f"{BASE}/orders/{order_id}/cancel", headers=HEADERS) # refundJavaScript (Node 18+)
const BASE = "https://api.adaotp.com/api/v1";
const headers = { "X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json" };
const res = await fetch(`${BASE}/orders`, {
method: "POST",
headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
body: JSON.stringify({ service_id: 1276, country: 184809 }),
}).then(r => r.json());
if (!res.success) throw new Error(`${res.error_code}: ${res.message}`);
const id = res.order.order_uuid;
for (let i = 0; i < 120; i++) {
const { data } = await fetch(`${BASE}/orders/${id}`, { headers }).then(r => r.json());
if (data.latest_code) { console.log("OTP:", data.latest_code); break; }
await new Promise(r => setTimeout(r, 5000));
}PHP
<?php
$base = 'https://api.adaotp.com/api/v1';
$key = 'YOUR_API_KEY';
$call = function (string $method, string $path, array $body = []) use ($base, $key) {
$ch = curl_init($base . $path);
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: ' . $key, 'Content-Type: application/json'],
CURLOPT_POSTFIELDS => $body ? json_encode($body) : null,
]);
return json_decode(curl_exec($ch), true);
};
$order = $call('POST', '/orders', ['service_id' => 1276, 'country' => 184809]);
if (!$order['success']) exit($order['error_code']);
$id = $order['order']['order_uuid'];
do {
sleep(5);
$o = $call('GET', "/orders/{$id}")['data'];
} while (!$o['latest_code'] && !$o['is_expired']);
echo $o['latest_code'];Account
Balance and profile of the API key owner.
/balance
Get balance
Live balance. Cached for up to 5 seconds.
curl -X GET 'https://api.adaotp.com/api/v1/balance' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"balance": 305932,
"balance_formatted": "Rp 305.932",
"bonus_balance": 0,
"pending_balance": 0,
"currency": "IDR"
},
"message": "Balance retrieved successfully"
}
/profile
Get profile
Account details and active-order stats. The balance here may lag a few seconds behind /balance.
curl -X GET 'https://api.adaotp.com/api/v1/profile' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"user": {
"id": 2621,
"name": "Jane",
"email": "[email protected]",
"balance": "Rp 305.932",
"created_at": "2026-01-01T00:00:00.000000Z"
},
"stats": {
"total_orders": 1,
"total_sms": 0,
"balance_raw": 305932
}
},
"message": "Profile loaded successfully"
}
Virtual numbers (SMS OTP)
Rent a phone number, receive the verification SMS, then finish or cancel. Cancelling before an SMS arrives refunds the full price.
/services
List services
All apps/websites you can receive codes for. Cache this list; it rarely changes.
curl -X GET 'https://api.adaotp.com/api/v1/services' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": [
{
"id": 1276,
"text": "Whatsapp",
"description": null,
"icon": "https://…/svc_ic_1276.webp"
},
{
"id": 718,
"text": "Google / Youtube / Gmail",
"description": null,
"icon": "https://…"
}
],
"message": "Services retrieved successfully"
}
/services/{id}
Get one service
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | integer | yes | Service id from /services |
curl -X GET 'https://api.adaotp.com/api/v1/services/1276' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"id": 1276,
"text": "Whatsapp",
"description": null,
"icon": "https://…"
},
"message": "Service details retrieved successfully"
}
/services/{id}/countries
Countries & prices for a service
Each entry is one purchasable offer (country + server + operator). Use the entry id as country when creating an order. stock, delivery_percent and can_order help you choose; prices change, so read them right before ordering.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | integer | yes | Service id from /services |
curl -X GET 'https://api.adaotp.com/api/v1/services/1276/countries' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"status": "success",
"application_id": 1276,
"countries": [
{
"id": 184809,
"name": "Indonesia",
"iso": "ID",
"prefix": "+62",
"price": 4720,
"price_formatted": "Rp 4.720",
"available": true,
"provider_id": 3,
"stock": 110,
"delivery_percent": 35.8,
"operator": "any",
"can_order": true
}
]
},
"message": "Service countries retrieved successfully"
}
/orders
Idempotency-Key Buy a number
Charges your balance and reserves a number. Read order.order_uuid from the response and poll GET /orders/{order_uuid} for the SMS. With quantity > 1 the response also has orders and summary. The first 3 numbers are created before the response; above 3 the API answers 202 with background: true and keeps ordering the rest — poll GET /orders/bulk-status for progress. Ordering stops at the first number that cannot be created (out of stock, balance); you are only charged for numbers created.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
service_id |
body | integer | yes | Service id from /services |
country |
body | integer | yes | Offer id from /services/{id}/countries (not an ISO code) |
quantity |
body | integer | no | How many numbers to buy, 1–30 (default 1) |
curl -X POST 'https://api.adaotp.com/api/v1/orders' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"service_id":1276,"country":184809,"quantity":1}'
{
"success": true,
"data": {
"results": [
{
"success": true,
"order_uuid": "FBTO1234567890NUM",
"order": {
"…": "raw order object"
}
}
],
"summary": {
"requested": 1,
"succeeded": 1,
"failed": 0
}
},
"order": {
"id": 6751431,
"order_uuid": "FBTO1234567890NUM",
"number": "6281234567890",
"formatted_number": "+62 812-3456-7890",
"status": "pending",
"service": {
"id": 1276,
"name": "Whatsapp"
},
"country": {
"id": 6,
"name": "Indonesia",
"iso_code": "ID",
"phone_code": "62"
},
"price": 4720,
"currency": "IDR",
"latest_code": null,
"sms_count": 0,
"messages": [],
"is_expired": false,
"remaining_time": 1200,
"created_at": "2026-10-09 08:15:09",
"expired_at": "2026-10-09 08:35:09"
},
"message": "Order created successfully"
}
Typical errors:
insufficient_balance, out_of_stock, rate_limited, provider_unavailable, validation_error
/orders/bulk-status
Progress of a multi-number order
Status of your latest order with quantity > 3 (kept 30 minutes). state is running while the rest are being ordered and done when finished; succeeded counts numbers created so far. data is null when there is no recent bulk order. Only one bulk order can run at a time (a second one gets 409).
curl -X GET 'https://api.adaotp.com/api/v1/orders/bulk-status' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"id": "3f9a1c2b7d10",
"state": "running",
"requested": 30,
"succeeded": 12,
"failed": 0,
"message": null,
"started_at": 1791520000,
"updated_at": 1791520014
}
}
/orders/{id}
Get one order (poll for the SMS)
Recommended polling endpoint. latest_code holds the newest code; messages lists every SMS newest-first. Poll every 5–10 seconds; responses are cached for 3 seconds. {id} is the order_uuid (works for any order) or the numeric id (active orders only).
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string | yes | order_uuid (recommended) or numeric order id |
check_sms |
query | boolean | no | true (default) asks the provider for new SMS now; false returns stored data only |
curl -X GET 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"id": 6751431,
"order_uuid": "FBTO1234567890NUM",
"number": "6281234567890",
"formatted_number": "+62 812-3456-7890",
"status": "completed",
"service": {
"id": 1276,
"name": "Whatsapp"
},
"country": {
"id": 6,
"name": "Indonesia",
"iso_code": "ID",
"phone_code": "62"
},
"operator": "any",
"price": 4720,
"currency": "IDR",
"latest_code": "504374",
"sms_count": 1,
"messages": [
{
"code": "504374",
"text": "Your WhatsApp code: 504-374",
"received_at": "2026-10-09T08:16:02+07:00"
}
],
"can_cancel": false,
"can_finish": true,
"is_expired": false,
"remaining_time": 912,
"created_at": "2026-10-09 08:15:09",
"expired_at": "2026-10-09 08:35:09"
},
"message": "Order retrieved successfully"
}
Typical errors:
order_not_found
/orders/active
List active orders
All orders still waiting or receiving SMS, plus your order limits. SMS arrays here are oldest-first; prefer GET /orders/{id} when you need the latest code.
curl -X GET 'https://api.adaotp.com/api/v1/orders/active' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"success": true,
"orders": [
{
"id": 6751431,
"order_uuid": "FBTO1234567890NUM",
"number": "6281234567890",
"status": "pending",
"sms": [],
"remaining_time": 1150
}
],
"count": 1,
"has_active_orders": true,
"order_limits": {
"…": "…"
}
},
"message": "Active orders retrieved successfully"
}
/orders/history
Order history (completed)
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | no | Page number |
per_page |
query | integer | no | Rows per page, 1–50 (default 10) |
date_from |
query | string | no | Y-m-d |
date_to |
query | string | no | Y-m-d |
search |
query | string | no | Number or service name |
sort_direction |
query | string | no | asc | desc (default desc) |
curl -X GET 'https://api.adaotp.com/api/v1/orders/history' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": [
{
"id": 6751431,
"order_uuid": "FBTO1234567890NUM",
"number": "6281234567890",
"status": "completed",
"price": 4720,
"sms": [
{
"code": "504374",
"text": "…",
"timestamp": "2026-10-09T08:16:02+07:00"
}
]
}
],
"pagination": {
"current_page": 1,
"per_page": 10,
"has_more_pages": false,
"last_page": 1
},
"message": "Completed order history retrieved successfully"
}
/orders/{id}/cancel
Cancel an order (refund)
Allowed only before an SMS arrives, and usually only after a short minimum wait (cancel_not_allowed_yet until then). DELETE /orders/{id} does the same.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string | yes | order_uuid or numeric order id |
curl -X POST 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM/cancel' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"message": "Order cancelled successfully",
"data": null
}
Typical errors:
cancel_not_allowed_yet, order_already_cancelled, order_not_found
/orders/{id}
Cancel an order (alias)
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string | yes | order_uuid or numeric order id |
curl -X DELETE 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"message": "Order cancelled successfully",
"data": null
}
/orders/{id}/finish
Finish an order
Mark the order complete after you received the code. Frees your active-order slot.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | string | yes | order_uuid or numeric order id |
curl -X POST 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM/finish' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"message": "Order completed successfully",
"data": null
}
Social media services (SMM)
Followers, likes, views and more for Instagram, TikTok, YouTube, Facebook, Telegram and other platforms. Delivery is automatic; poll the order for progress.
/smm/platforms
List platforms & service types
curl -X GET 'https://api.adaotp.com/api/v1/smm/platforms' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"platforms": [
{
"key": "instagram",
"label": "Instagram",
"total": 870,
"types": [
{
"type": "Followers",
"total": 197
},
{
"type": "Likes",
"total": 198
}
]
}
]
},
"message": "OK"
}
/smm/services
List services
Always filter by platform + type; unfiltered responses are large. price_per_1000 is in IDR.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
platform |
query | string | no | Platform key from /smm/platforms |
type |
query | string | no | Service type within the platform |
category |
query | string | no | Legacy category name (overrides platform/type) |
sort |
query | string | no | quality (default) | price_asc | price_desc |
curl -X GET 'https://api.adaotp.com/api/v1/smm/services' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"services": [
{
"id": 8112,
"name": "Instagram Followers Indonesia [Refill 30 days]",
"platform": "instagram",
"service_type": "Followers",
"type": "Default",
"is_custom": false,
"price_per_1000": 72000,
"min": 50,
"max": 50000,
"refill": 0,
"target_label": "Profile link / username",
"completion_rate": 89,
"refund_rate": 8,
"is_recommended": false
}
]
},
"message": "OK"
}
/smm/services/{id}
Get one service
Current price and min/max — call right before ordering.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
id |
path | integer | yes | Service id |
curl -X GET 'https://api.adaotp.com/api/v1/smm/services/8112' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"id": 8112,
"name": "…",
"price_per_1000": 72000,
"min": 50,
"max": 50000
},
"message": "OK"
}
/smm/quote
Calculate price
Preview the price. Does not charge your balance.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
service_id |
body | integer | yes | Service id |
quantity |
body | integer | no | Required for normal services |
custom_comments |
body | string | no | Custom-comment services only: one comment per line (quantity = number of lines) |
curl -X POST 'https://api.adaotp.com/api/v1/smm/quote' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"service_id":8112,"quantity":1000}'
{
"success": true,
"data": {
"quantity": 1000,
"price": 72000
},
"message": "OK"
}
/smm/orders
Idempotency-Key Place an SMM order
| Name | In | Type | Required | Description |
|---|---|---|---|---|
service_id |
body | integer | yes | Service id |
target |
body | string | yes | Link or username, as described by the service target_label |
quantity |
body | integer | no | Between the service min and max |
custom_comments |
body | string | no | Custom-comment services only, one per line |
curl -X POST 'https://api.adaotp.com/api/v1/smm/orders' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"service_id":8112,"target":"https://instagram.com/username","quantity":1000}'
{
"success": true,
"data": {
"order_uuid": "9f1c2f7a-6b41-4a0e-9d2e-1a2b3c4d5e6f",
"service_id": 8112,
"target": "https://instagram.com/username",
"quantity": 1000,
"price": 72000,
"status": "pending"
},
"message": "Order placed successfully"
}
Typical errors:
insufficient_balance, validation_error, order_failed
/smm/orders
List SMM orders
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | no | Page number |
per_page |
query | integer | no | 1–100 (default 25) |
status |
query | string | no | pending | processing | in_progress | completed | partial | canceled | failed | refunded |
curl -X GET 'https://api.adaotp.com/api/v1/smm/orders' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"orders": [
{
"order_uuid": "9f1c2f7a-…",
"status": "in_progress",
"start_count": 1520,
"remains": 400
}
],
"pagination": {
"…": "…"
}
},
"message": "OK"
}
/smm/orders/{uuid}
Get one SMM order
Refreshed from the provider. remains = quantity not yet delivered; refunded = IDR returned for undelivered parts.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X GET 'https://api.adaotp.com/api/v1/smm/orders/9f1c2f7a-6b41-4a0e-9d2e-1a2b3c4d5e6f' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order_uuid": "9f1c2f7a-…",
"service_name": "…",
"target": "…",
"quantity": 1000,
"price": 72000,
"status": "completed",
"start_count": 1520,
"remains": 0,
"refunded": 0,
"created_at": "2026-10-09T08:00:00+07:00"
},
"message": "OK"
}
Gmail accounts
Ready-made Gmail accounts. Credentials are returned immediately and can be read again from your orders. Treat passwords as secrets.
/gmail/stock
Stock & price
curl -X GET 'https://api.adaotp.com/api/v1/gmail/stock' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"stock": 814,
"sell_price": 5880,
"max_qty": 50
},
"message": "OK"
}
/gmail/orders
Idempotency-Key Buy Gmail accounts
Charged up front; anything that cannot be delivered is refunded automatically.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
qty |
body | integer | yes | 1–50 (see max_qty) |
curl -X POST 'https://api.adaotp.com/api/v1/gmail/orders' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"qty":1}'
{
"success": true,
"data": {
"orders": [
{
"order_uuid": "c1d2…",
"email": "[email protected]",
"password": "••••••••",
"price": 5880,
"status": "completed",
"refundable": true,
"deadline_at": "2026-10-10T08:00:00+07:00"
}
]
},
"message": "Purchase completed"
}
Typical errors:
insufficient_balance, out_of_stock, validation_error
/gmail/orders
List Gmail orders
| Name | In | Type | Required | Description |
|---|---|---|---|---|
page |
query | integer | no | Page number |
per_page |
query | integer | no | 1–100 |
status |
query | string | no | pending | completed | failed | refund_pending | refunded | refund_rejected |
curl -X GET 'https://api.adaotp.com/api/v1/gmail/orders' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"orders": [
{
"order_uuid": "c1d2…",
"email": "[email protected]",
"password": "••••••••",
"status": "completed"
}
]
},
"message": "OK"
}
/gmail/orders/{uuid}
Get one Gmail order
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X GET 'https://api.adaotp.com/api/v1/gmail/orders/c1d2e3f4-…' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order_uuid": "c1d2…",
"email": "[email protected]",
"password": "••••••••",
"status": "completed",
"refund_status": null,
"refundable": true
},
"message": "OK"
}
/gmail/orders/{uuid}/refund
File a refund dispute
Send as multipart/form-data while refundable is true. A screenshot proving the problem is required.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
reason |
body | string | yes | 10–1000 characters |
proof |
body | file | yes | Screenshot: jpg/png/webp, max 5 MB |
curl -X POST 'https://api.adaotp.com/api/v1/gmail/orders/c1d2e3f4-…/refund' \ -H 'X-API-Key: YOUR_API_KEY' \ -F 'reason=Password is wrong, cannot sign in' \ -F '[email protected]'
{
"success": true,
"data": {
"refund_status": "pending"
},
"message": "OK"
}
/gmail/orders/{uuid}/chat
Dispute chat link
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X GET 'https://api.adaotp.com/api/v1/gmail/orders/c1d2e3f4-…/chat' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"url": "https://…"
},
"message": "OK"
}
Email rental
Rent an email address to receive one verification code. Cancel for a full refund if the code never arrives.
/email-rental/suggestions
Popular target sites
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/suggestions' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"sites": [
"tiktok.com",
"facebook.com",
"instagram.com",
"x.com",
"github.com"
]
},
"message": "OK"
}
/email-rental/domains
Domains & prices for a site
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site |
query | string | yes | Target site |
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/domains?site=tiktok.com' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"domains": [
{
"name": "outlook.com",
"count": 740,
"price": 140,
"completed": 24500
},
{
"name": "gmx.com",
"count": 730628,
"price": 124,
"completed": 11752
}
],
"used_domains": []
},
"message": "OK"
}
/email-rental/orders
Idempotency-Key Rent an address
Charges your balance and returns the address. Poll GET /email-rental/orders/{uuid} until code is filled.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
site |
body | string | yes | Target site |
domain |
body | string | yes | Domain name from /email-rental/domains |
curl -X POST 'https://api.adaotp.com/api/v1/email-rental/orders' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"site":"tiktok.com","domain":"outlook.com"}'
{
"success": true,
"data": {
"order_uuid": "e5f6…",
"site": "tiktok.com",
"domain": "hotmail.com",
"email": "[email protected]",
"code": null,
"price": 140,
"status": "waiting",
"cancellable": true
},
"message": "OK"
}
Typical errors:
insufficient_balance, service_unavailable, out_of_stock
/email-rental/orders
List rentals
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/orders' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"orders": [
{
"order_uuid": "e5f6…",
"email": "[email protected]",
"code": "482913",
"status": "completed"
}
]
},
"message": "OK"
}
/email-rental/orders/{uuid}
Get one rental (poll for the code)
Checks the mailbox each call. Poll every 5–10 seconds.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/orders/e5f6a7b8-…' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order_uuid": "e5f6…",
"email": "[email protected]",
"code": "482913",
"message": "Your TikTok code is 482913",
"status": "completed",
"cancellable": false
},
"message": "OK"
}
/email-rental/orders/{uuid}/cancel
Cancel a rental (refund)
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X POST 'https://api.adaotp.com/api/v1/email-rental/orders/e5f6a7b8-…/cancel' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"status": "canceled"
},
"message": "OK"
}
WhatsApp Ready numbers
Numbers whose WhatsApp account is already active. Sign in with "Link with phone number / use your other phone": request a 6-digit code, enter it in WhatsApp, then confirm. Flow: ready → waiting_code → code_sent → completed. failed / canceled / refunded return the price to your balance.
/wa-ready/info
Countries, prices & stock
curl -X GET 'https://api.adaotp.com/api/v1/wa-ready/info' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"enabled": true,
"countries": [
{
"iso": "ID",
"name": "Indonesia",
"price": 13200,
"stock": 25
}
]
},
"message": "OK"
}
/wa-ready/orders
Idempotency-Key Buy a WhatsApp number
| Name | In | Type | Required | Description |
|---|---|---|---|---|
country |
body | string | yes | ISO 3166-1 alpha-2 from /wa-ready/info |
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"country":"ID"}'
{
"success": true,
"data": {
"order": {
"order_uuid": "3b9d…",
"phone": "+6285860348151",
"country": "ID",
"price": 13200,
"status": "ready"
}
},
"message": "Number purchased"
}
Typical errors:
insufficient_balance, out_of_stock, provider_unavailable
/wa-ready/orders
List WhatsApp orders
curl -X GET 'https://api.adaotp.com/api/v1/wa-ready/orders' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"orders": [
{
"order_uuid": "3b9d…",
"phone": "+6285860348151",
"status": "completed"
}
]
},
"message": "OK"
}
/wa-ready/orders/{uuid}
Get order status (poll for the code)
Poll every 3–5 seconds while waiting_code. Always use latest_code. Allowed actions are given by the can_* flags.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X GET 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order": {
"order_uuid": "3b9d…",
"phone": "+6285860348151",
"status": "code_sent",
"latest_code": "482913",
"can_confirm": true,
"can_cancel": false,
"can_dispute": true
}
},
"message": "OK"
}
/wa-ready/orders/{uuid}/request-code
Request the 6-digit code
Start the "link with phone number" flow in WhatsApp first, then call this.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/request-code' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order": {
"status": "waiting_code"
}
},
"message": "OK"
}
/wa-ready/orders/{uuid}/confirm
Confirm successful sign-in
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/confirm' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order": {
"status": "completed"
}
},
"message": "OK"
}
/wa-ready/orders/{uuid}/cancel
Cancel (refund)
Only while can_cancel is true (before a code was received).
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/cancel' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"order": {
"status": "canceled"
}
},
"message": "OK"
}
/wa-ready/orders/{uuid}/dispute
File a complaint (refund)
multipart/form-data, only while can_dispute. Approved → refunded; follow replies in the order messages.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
reason |
body | string | yes | 5–1000 characters |
image |
body | file | yes | Screenshot: jpg/png/webp, max 4 MB |
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/dispute' \ -H 'X-API-Key: YOUR_API_KEY' \ -F 'reason=WhatsApp rejected the latest code' \ -F '[email protected]'
{
"success": true,
"data": {
"order": {
"dispute_status": "pending"
}
},
"message": "OK"
}
/wa-ready/orders/{uuid}/message
Reply in the complaint thread
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uuid |
path | string | yes | order_uuid |
body |
body | string | yes | Up to 1000 characters |
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/message' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"body":"Screenshot attached above"}'
{
"success": true,
"data": {
"order": {
"…": "…"
}
},
"message": "OK"
}
Deposits & transactions
Top up your balance from code. Payment instructions (QR / virtual account / checkout URL) come back in the deposit response.
/payment-methods
List payment methods
curl -X GET 'https://api.adaotp.com/api/v1/payment-methods' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": [
{
"id": 12,
"name": "Qris Asia",
"category_name": "Payment Gateway",
"expiration_time": 5
}
],
"message": "OK"
}
/deposits
Idempotency-Key Create a deposit (IDR)
Returns the transaction with payment instructions (QR image as qr_code_base64 or a payment_url). Poll GET /transactions/{uniqcode} for the status.
| Name | In | Type | Required | Description |
|---|---|---|---|---|
amount |
body | integer | yes | IDR, minimum 10000 |
method |
body | integer | yes | Payment method id from /payment-methods |
curl -X POST 'https://api.adaotp.com/api/v1/deposits' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"amount":50000,"method":12}'
{
"success": true,
"data": {
"uniqcode_tx": "TX…",
"amount": 50000,
"total_amount": 50123,
"status": "pending",
"qr_code_base64": "iVBOR…",
"expires_at_iso": "2026-10-09T08:05:00+07:00"
},
"message": "OK"
}
/deposits/crypto
Idempotency-Key Create a crypto deposit (USD)
| Name | In | Type | Required | Description |
|---|---|---|---|---|
amount |
body | number | yes | USD, 1–10000 |
curl -X POST 'https://api.adaotp.com/api/v1/deposits/crypto' \
-H 'X-API-Key: YOUR_API_KEY' \
-H 'Idempotency-Key: 2f6c1b9e-1d0a-4c55-9a4e-6b8f2c7d1e03' \
-H 'Content-Type: application/json' \
-d '{"amount":10}'
{
"success": true,
"data": {
"checkout_url": "https://…"
},
"message": "OK"
}
/transactions
List deposits
curl -X GET 'https://api.adaotp.com/api/v1/transactions' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"transactions": [
{
"uniqcode_tx": "TX…",
"type": "deposit",
"amount": 50000,
"fee": 0,
"total_amount": 50123,
"status": "success",
"status_label": "Success",
"payment_method": {
"…": "…"
},
"payment_url": null,
"created_at_iso": "2026-10-09T08:00:00+07:00"
}
],
"pagination": {
"…": "…"
}
},
"message": "OK"
}
/transactions/{uniqcode}
Get one deposit
| Name | In | Type | Required | Description |
|---|---|---|---|---|
uniqcode |
path | string | yes | uniqcode_tx from the deposit / transaction list |
curl -X GET 'https://api.adaotp.com/api/v1/transactions/TX…' \ -H 'X-API-Key: YOUR_API_KEY'
{
"success": true,
"data": {
"uniqcode_tx": "TX…",
"amount": 50000,
"total_amount": 50123,
"status": "pending",
"expires_in_seconds": 290,
"qr_code_base64": "iVBOR…",
"payment_url": null
},
"message": "OK"
}
Error codes
Every error looks like this. Branch on error_code; quote request_id when contacting support.
{
"success": false,
"message": "Insufficient balance",
"error_code": "insufficient_balance",
"request_id": "6f1d2c3b-8a9e-4b7c-9d1e-2f3a4b5c6d7e"
}
| error_code | HTTP | Meaning |
|---|---|---|
unauthenticated | 401 | No API key was sent. |
invalid_api_key | 401 | The API key is wrong or the account is disabled. |
api_key_wrong_domain | 401 | The key belongs to a different site. Use the site where you registered. |
validation_error | 422 | A parameter is missing or invalid. Details per field are in errors. |
insufficient_balance | 422 | Not enough balance. Top up and retry. |
out_of_stock | 422 | No stock for this choice right now. Pick another country/server or retry in a few minutes. |
service_unavailable | 422 | The service or target site is not supported right now. |
order_failed | 422 | The provider rejected the order. Nothing was charged (or it was refunded). |
cancel_not_allowed_yet | 422 | The order cannot be cancelled yet. Retry shortly. |
order_already_cancelled | 422 | The order was already cancelled. |
provider_unavailable | 422 | The upstream provider is temporarily unavailable or restricted. Retry later. |
upstream_error | 422 | Any other failure reported by the provider. Read message. |
idempotency_key_reused | 422 | This Idempotency-Key was already used with different parameters. |
order_not_found | 404 | No such order for this API key. |
not_found | 404 | Unknown endpoint or resource. |
product_unavailable | 404 | This product is not offered on this site. |
idempotency_in_progress | 409 | The first request with this Idempotency-Key is still running. Retry in a few seconds. |
rate_limited | 429 | Too many requests. Wait and retry. |
server_error | 500 | Unexpected error on our side. Retry; contact support with the request_id if it persists. |
Validation errors (validation_error) also include errors: an object of field → list of messages.