AdaOTP

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).

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

Quick start: receive an SMS code

  1. Check your balance — GET /balance
  2. Find the service id (e.g. WhatsApp) — GET /services
  3. List countries & prices for that service; pick an entry id — GET /services/{service_id}/countries
  4. Buy a number — POST /orders
  5. Poll every 5–10 s until latest_code is filled — GET /orders/{order_uuid}
  6. 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)  # refund
JavaScript (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.

GET /balance

Get balance

Live balance. Cached for up to 5 seconds.

Request
curl -X GET 'https://api.adaotp.com/api/v1/balance' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "balance": 305932,
        "balance_formatted": "Rp 305.932",
        "bonus_balance": 0,
        "pending_balance": 0,
        "currency": "IDR"
    },
    "message": "Balance retrieved successfully"
}
GET /profile

Get profile

Account details and active-order stats. The balance here may lag a few seconds behind /balance.

Request
curl -X GET 'https://api.adaotp.com/api/v1/profile' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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.

GET /services

List services

All apps/websites you can receive codes for. Cache this list; it rarely changes.

Request
curl -X GET 'https://api.adaotp.com/api/v1/services' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
GET /services/{id}

Get one service

Parameters
NameInTypeRequiredDescription
id path integer yes Service id from /services
Request
curl -X GET 'https://api.adaotp.com/api/v1/services/1276' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "id": 1276,
        "text": "Whatsapp",
        "description": null,
        "icon": "https://…"
    },
    "message": "Service details retrieved successfully"
}
GET /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.

Parameters
NameInTypeRequiredDescription
id path integer yes Service id from /services
Request
curl -X GET 'https://api.adaotp.com/api/v1/services/1276/countries' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
POST /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.

Parameters
NameInTypeRequiredDescription
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)
Request
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}'
Response 201
{
    "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

GET /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).

Request
curl -X GET 'https://api.adaotp.com/api/v1/orders/bulk-status' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "id": "3f9a1c2b7d10",
        "state": "running",
        "requested": 30,
        "succeeded": 12,
        "failed": 0,
        "message": null,
        "started_at": 1791520000,
        "updated_at": 1791520014
    }
}
GET /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).

Parameters
NameInTypeRequiredDescription
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
Request
curl -X GET 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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

GET /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.

Request
curl -X GET 'https://api.adaotp.com/api/v1/orders/active' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
GET /orders/history

Order history (completed)

Parameters
NameInTypeRequiredDescription
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)
Request
curl -X GET 'https://api.adaotp.com/api/v1/orders/history' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
POST /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.

Parameters
NameInTypeRequiredDescription
id path string yes order_uuid or numeric order id
Request
curl -X POST 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM/cancel' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "message": "Order cancelled successfully",
    "data": null
}

Typical errors: cancel_not_allowed_yet, order_already_cancelled, order_not_found

DELETE /orders/{id}

Cancel an order (alias)

Parameters
NameInTypeRequiredDescription
id path string yes order_uuid or numeric order id
Request
curl -X DELETE 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "message": "Order cancelled successfully",
    "data": null
}
POST /orders/{id}/finish

Finish an order

Mark the order complete after you received the code. Frees your active-order slot.

Parameters
NameInTypeRequiredDescription
id path string yes order_uuid or numeric order id
Request
curl -X POST 'https://api.adaotp.com/api/v1/orders/FBTO1234567890NUM/finish' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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.

GET /smm/platforms

List platforms & service types

Request
curl -X GET 'https://api.adaotp.com/api/v1/smm/platforms' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "platforms": [
            {
                "key": "instagram",
                "label": "Instagram",
                "total": 870,
                "types": [
                    {
                        "type": "Followers",
                        "total": 197
                    },
                    {
                        "type": "Likes",
                        "total": 198
                    }
                ]
            }
        ]
    },
    "message": "OK"
}
GET /smm/services

List services

Always filter by platform + type; unfiltered responses are large. price_per_1000 is in IDR.

Parameters
NameInTypeRequiredDescription
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
Request
curl -X GET 'https://api.adaotp.com/api/v1/smm/services' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
GET /smm/services/{id}

Get one service

Current price and min/max — call right before ordering.

Parameters
NameInTypeRequiredDescription
id path integer yes Service id
Request
curl -X GET 'https://api.adaotp.com/api/v1/smm/services/8112' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "id": 8112,
        "name": "…",
        "price_per_1000": 72000,
        "min": 50,
        "max": 50000
    },
    "message": "OK"
}
POST /smm/quote

Calculate price

Preview the price. Does not charge your balance.

Parameters
NameInTypeRequiredDescription
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)
Request
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}'
Response 200
{
    "success": true,
    "data": {
        "quantity": 1000,
        "price": 72000
    },
    "message": "OK"
}
POST /smm/orders Idempotency-Key

Place an SMM order

Parameters
NameInTypeRequiredDescription
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
Request
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}'
Response 201
{
    "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

GET /smm/orders

List SMM orders

Parameters
NameInTypeRequiredDescription
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
Request
curl -X GET 'https://api.adaotp.com/api/v1/smm/orders' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "orders": [
            {
                "order_uuid": "9f1c2f7a-…",
                "status": "in_progress",
                "start_count": 1520,
                "remains": 400
            }
        ],
        "pagination": {
            "…": "…"
        }
    },
    "message": "OK"
}
GET /smm/orders/{uuid}

Get one SMM order

Refreshed from the provider. remains = quantity not yet delivered; refunded = IDR returned for undelivered parts.

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X GET 'https://api.adaotp.com/api/v1/smm/orders/9f1c2f7a-6b41-4a0e-9d2e-1a2b3c4d5e6f' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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.

GET /gmail/stock

Stock & price

Request
curl -X GET 'https://api.adaotp.com/api/v1/gmail/stock' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "stock": 814,
        "sell_price": 5880,
        "max_qty": 50
    },
    "message": "OK"
}
POST /gmail/orders Idempotency-Key

Buy Gmail accounts

Charged up front; anything that cannot be delivered is refunded automatically.

Parameters
NameInTypeRequiredDescription
qty body integer yes 1–50 (see max_qty)
Request
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}'
Response 201
{
    "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

GET /gmail/orders

List Gmail orders

Parameters
NameInTypeRequiredDescription
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
Request
curl -X GET 'https://api.adaotp.com/api/v1/gmail/orders' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "orders": [
            {
                "order_uuid": "c1d2…",
                "email": "[email protected]",
                "password": "••••••••",
                "status": "completed"
            }
        ]
    },
    "message": "OK"
}
GET /gmail/orders/{uuid}

Get one Gmail order

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X GET 'https://api.adaotp.com/api/v1/gmail/orders/c1d2e3f4-…' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "order_uuid": "c1d2…",
        "email": "[email protected]",
        "password": "••••••••",
        "status": "completed",
        "refund_status": null,
        "refundable": true
    },
    "message": "OK"
}
POST /gmail/orders/{uuid}/refund

File a refund dispute

Send as multipart/form-data while refundable is true. A screenshot proving the problem is required.

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
reason body string yes 10–1000 characters
proof body file yes Screenshot: jpg/png/webp, max 5 MB
Request
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]'
Response 200
{
    "success": true,
    "data": {
        "refund_status": "pending"
    },
    "message": "OK"
}
GET /gmail/orders/{uuid}/chat

Dispute chat link

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X GET 'https://api.adaotp.com/api/v1/gmail/orders/c1d2e3f4-…/chat' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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.

GET /email-rental/suggestions

Popular target sites

Request
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/suggestions' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "sites": [
            "tiktok.com",
            "facebook.com",
            "instagram.com",
            "x.com",
            "github.com"
        ]
    },
    "message": "OK"
}
GET /email-rental/domains

Domains & prices for a site

Parameters
NameInTypeRequiredDescription
site query string yes Target site
Request
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/domains?site=tiktok.com' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
POST /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.

Parameters
NameInTypeRequiredDescription
site body string yes Target site
domain body string yes Domain name from /email-rental/domains
Request
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"}'
Response 201
{
    "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

GET /email-rental/orders

List rentals

Request
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/orders' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "orders": [
            {
                "order_uuid": "e5f6…",
                "email": "[email protected]",
                "code": "482913",
                "status": "completed"
            }
        ]
    },
    "message": "OK"
}
GET /email-rental/orders/{uuid}

Get one rental (poll for the code)

Checks the mailbox each call. Poll every 5–10 seconds.

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X GET 'https://api.adaotp.com/api/v1/email-rental/orders/e5f6a7b8-…' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "order_uuid": "e5f6…",
        "email": "[email protected]",
        "code": "482913",
        "message": "Your TikTok code is 482913",
        "status": "completed",
        "cancellable": false
    },
    "message": "OK"
}
POST /email-rental/orders/{uuid}/cancel

Cancel a rental (refund)

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X POST 'https://api.adaotp.com/api/v1/email-rental/orders/e5f6a7b8-…/cancel' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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.

GET /wa-ready/info

Countries, prices & stock

Request
curl -X GET 'https://api.adaotp.com/api/v1/wa-ready/info' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "enabled": true,
        "countries": [
            {
                "iso": "ID",
                "name": "Indonesia",
                "price": 13200,
                "stock": 25
            }
        ]
    },
    "message": "OK"
}
POST /wa-ready/orders Idempotency-Key

Buy a WhatsApp number

Parameters
NameInTypeRequiredDescription
country body string yes ISO 3166-1 alpha-2 from /wa-ready/info
Request
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"}'
Response 201
{
    "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

GET /wa-ready/orders

List WhatsApp orders

Request
curl -X GET 'https://api.adaotp.com/api/v1/wa-ready/orders' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "orders": [
            {
                "order_uuid": "3b9d…",
                "phone": "+6285860348151",
                "status": "completed"
            }
        ]
    },
    "message": "OK"
}
GET /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.

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X GET 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
POST /wa-ready/orders/{uuid}/request-code

Request the 6-digit code

Start the "link with phone number" flow in WhatsApp first, then call this.

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/request-code' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "order": {
            "status": "waiting_code"
        }
    },
    "message": "OK"
}
POST /wa-ready/orders/{uuid}/confirm

Confirm successful sign-in

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/confirm' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "order": {
            "status": "completed"
        }
    },
    "message": "OK"
}
POST /wa-ready/orders/{uuid}/cancel

Cancel (refund)

Only while can_cancel is true (before a code was received).

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
Request
curl -X POST 'https://api.adaotp.com/api/v1/wa-ready/orders/3b9d…/cancel' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": {
        "order": {
            "status": "canceled"
        }
    },
    "message": "OK"
}
POST /wa-ready/orders/{uuid}/dispute

File a complaint (refund)

multipart/form-data, only while can_dispute. Approved → refunded; follow replies in the order messages.

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
reason body string yes 5–1000 characters
image body file yes Screenshot: jpg/png/webp, max 4 MB
Request
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]'
Response 200
{
    "success": true,
    "data": {
        "order": {
            "dispute_status": "pending"
        }
    },
    "message": "OK"
}
POST /wa-ready/orders/{uuid}/message

Reply in the complaint thread

Parameters
NameInTypeRequiredDescription
uuid path string yes order_uuid
body body string yes Up to 1000 characters
Request
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"}'
Response 200
{
    "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.

GET /payment-methods

List payment methods

Request
curl -X GET 'https://api.adaotp.com/api/v1/payment-methods' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "success": true,
    "data": [
        {
            "id": 12,
            "name": "Qris Asia",
            "category_name": "Payment Gateway",
            "expiration_time": 5
        }
    ],
    "message": "OK"
}
POST /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.

Parameters
NameInTypeRequiredDescription
amount body integer yes IDR, minimum 10000
method body integer yes Payment method id from /payment-methods
Request
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}'
Response 200
{
    "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"
}
POST /deposits/crypto Idempotency-Key

Create a crypto deposit (USD)

Parameters
NameInTypeRequiredDescription
amount body number yes USD, 1–10000
Request
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}'
Response 200
{
    "success": true,
    "data": {
        "checkout_url": "https://…"
    },
    "message": "OK"
}
GET /transactions

List deposits

Request
curl -X GET 'https://api.adaotp.com/api/v1/transactions' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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"
}
GET /transactions/{uniqcode}

Get one deposit

Parameters
NameInTypeRequiredDescription
uniqcode path string yes uniqcode_tx from the deposit / transaction list
Request
curl -X GET 'https://api.adaotp.com/api/v1/transactions/TX…' \
  -H 'X-API-Key: YOUR_API_KEY'
Response 200
{
    "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_codeHTTPMeaning
unauthenticated401No API key was sent.
invalid_api_key401The API key is wrong or the account is disabled.
api_key_wrong_domain401The key belongs to a different site. Use the site where you registered.
validation_error422A parameter is missing or invalid. Details per field are in errors.
insufficient_balance422Not enough balance. Top up and retry.
out_of_stock422No stock for this choice right now. Pick another country/server or retry in a few minutes.
service_unavailable422The service or target site is not supported right now.
order_failed422The provider rejected the order. Nothing was charged (or it was refunded).
cancel_not_allowed_yet422The order cannot be cancelled yet. Retry shortly.
order_already_cancelled422The order was already cancelled.
provider_unavailable422The upstream provider is temporarily unavailable or restricted. Retry later.
upstream_error422Any other failure reported by the provider. Read message.
idempotency_key_reused422This Idempotency-Key was already used with different parameters.
order_not_found404No such order for this API key.
not_found404Unknown endpoint or resource.
product_unavailable404This product is not offered on this site.
idempotency_in_progress409The first request with this Idempotency-Key is still running. Retry in a few seconds.
rate_limited429Too many requests. Wait and retry.
server_error500Unexpected 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.