Hướng dẫn API

Số dư$0.00

Hướng dẫn gọi API

Mua số và nhận mã OTP thẳng từ script của bạn, không cần mở trình duyệt. Dùng chung ví và chung bảng giá với tài khoản web — cộng tác viên gọi API vẫn được đúng giá chiết khấu của mình.

1. Lấy khoá API

Vào Thông tin tài khoản → tab API → bấm Cấp khoá mới. Khoá có dạng jp_xxxxxxxx…

Khoá chỉ hiện đúng một lần. Chép và cất ngay. Làm mất thì cấp lại được, nhưng cấp lại là khoá cũ chết ngay lập tức — mọi script đang chạy bằng khoá cũ sẽ dừng.

Khoá đi trong header, không nhét vào đường dẫn. Query string nằm trong log máy chủ, log CDN và lịch sử trình duyệt — bỏ khoá vào đó là phát tán nó ra mấy chỗ không xoá được.

bash
curl -H "Authorization: Bearer jp_khoacuaban" \
  https://www.jp-otp.com/api/v1/balance

Không đặt được header Authorization thì dùng X-API-Key: jp_khoacuaban, hiệu lực như nhau.

2. Lấy mã nhanh nhất — đọc kỹ mục này

Box GSM đẩy tin lên ngay khi có, cái nào về trước lên trước. Không theo thứ tự bạn mua. Mua 30 số thì mã hoàn toàn có thể về ở số thứ 17 trước số thứ nhất — mà số thứ nhất có khi không bao giờ có mã.

Hệ quả: đừng chờ lần lượt. Vòng lặp kiểu “chờ số 1 xong rồi mới xem số 2” sẽ ngồi chết ở số 1 suốt 20 phút trong khi mã của 29 số kia đã về từ lâu.

Cách sai

javascript
// ĐỪNG viết thế này
for (const don of donHang) {
  while (true) {
    const r = await fetch(`${GOC}/api/v1/orders/${don.order_id}`, { headers });
    const { order } = await r.json();
    if (order.otp) { console.log(order.phone, order.otp); break; }
    await nghi(2000);
  }
}
// Ket ở đơn đầu tiên. 30 đơn = 30 vòng chờ nối đuôi nhau.

Cách đúng

Mua cả nắm trong một lượt, rồi giữ một danh sách id đang chờ và hỏi cả danh sách bằng /api/v1/orders/wait. Đường này giữ kết nối và tự hỏi database mỗi giây, hễ có bất kỳ đơn nào có mã là trả về ngay — mã về giây thứ 3 thì bạn nhận ở giây thứ 3.

javascript
const GOC = 'https://www.jp-otp.com';
const headers = { Authorization: 'Bearer jp_khoacuaban', 'Content-Type': 'application/json' };

// 1) Mua cả nắm trong MỘT lượt
const mua = await fetch(`${GOC}/api/v1/orders`, {
  method: 'POST',
  headers,
  body: JSON.stringify({ service_id: 'ID_DICH_VU', quantity: 30 }),
}).then(r => r.json());

console.log(`Lay duoc ${mua.taken}/${mua.requested} so`);

// 2) Danh sach id CON DANG CHO
let dangCho = mua.orders.map(o => o.order_id);

// 3) Cho ca nam mot luc. Ai co ma truoc thi nhan truoc.
while (dangCho.length > 0) {
  const r = await fetch(
    `${GOC}/api/v1/orders/wait?timeout=55&ids=${dangCho.join(',')}`,
    { headers }
  ).then(r => r.json());

  for (const o of r.orders) {
    if (o.status === 'waiting') continue;

    if (o.otp) console.log('CO MA', o.phone, o.otp);
    else       console.log('hong ', o.phone, o.status);  // expired -> da hoan tien

    dangCho = dangCho.filter(id => id !== o.order_id);   // bo ra khoi danh sach cho
  }
}

Cùng việc đó bằng Python

python
import requests

GOC = 'https://www.jp-otp.com'
H = {'Authorization': 'Bearer jp_khoacuaban'}

mua = requests.post(f'{GOC}/api/v1/orders', headers=H,
                    json={'service_id': 'ID_DICH_VU', 'quantity': 30}).json()

dang_cho = [o['order_id'] for o in mua['orders']]

while dang_cho:
    r = requests.get(f'{GOC}/api/v1/orders/wait',
                     headers=H,
                     params={'timeout': 55, 'ids': ','.join(dang_cho)},
                     timeout=70).json()

    for o in r['orders']:
        if o['status'] == 'waiting':
            continue
        if o['otp']:
            print('CO MA', o['phone'], o['otp'])
        else:
            print('hong ', o['phone'], o['status'])
        dang_cho.remove(o['order_id'])

Bốn điều quyết định nhanh hay chậm

  1. Mua cả nắm trong một lượt gọi. quantity: 30 chạy trong một giao dịch duy nhất. Gọi 30 lượt riêng thì mất thêm 30 vòng mạng, mà còn dễ giành số với chính mình.
  2. Hỏi cả danh sách, đừng hỏi từng đơn. Một lượt gọi ?ids=a,b,c giục hết mọi đơn trong một câu lệnh database. Hỏi lần lượt 30 đơn là 30 vòng mạng, và mã của đơn cuối phải đợi hết 29 lượt trước mới tới lượt được nhìn tới.
  3. Dùng /wait thay vì tự gọi lại liên tục. Mỗi lượt gọi từ máy bạn phải qua TLS, qua khởi động serverless, qua kiểm khoá — vài trăm mili giây tiêu tốn mà chẳng để làm gì. Vòng lặp nằm sẵn trong máy chủ thì mỗi nhịp chỉ là một câu truy vấn.
  4. Bỏ đơn đã xong ra khỏi danh sách chờ. Nếu vẫn truyền id đã có mã, /wait thấy “có đơn không còn chờ” và trả về ngay — thành ra quay vòng liên tục, tốn mà không nhanh hơn.

Không dùng được /wait (môi trường chặn kết nối dài) thì gọi GET /api/v1/orders?ids=… mỗi 2 giây. Nhanh hơn nữa không giúp gì thêm mà chỉ tốn.

3. Các đường gọi

Gốc: https://www.jp-otp.com/api/v1 · Mọi câu trả lời đều có ok; lỗi thì kèm code và error.

GET/api/v1/balance

Ví, hạng và đơn vị tiền của tài khoản.

json
{ "ok": true, "username": "huygt", "balance": 152.4,
  "currency": "USD", "tier": "ctv" }
GET/api/v1/services

Danh mục dịch vụ. price là giá BẠN phải trả (đã trừ chiết khấu hạng của bạn); list_price là giá niêm yết.

json
{ "ok": true, "services": [
  { "service_id": "0a8d16f0-…", "service_name": "Facebook",
    "list_price": 0.5, "price": 0.2 }
]}
POST/api/v1/orders

Mua số. quantity từ 1 tới 30. Kho hoặc ví không đủ cho trọn số lượng thì lấy được bao nhiêu tính bấy nhiêu — xem taken.

bash
curl -X POST https://www.jp-otp.com/api/v1/orders \
  -H "Authorization: Bearer jp_khoacuaban" \
  -H "Content-Type: application/json" \
  -d '{"service_id":"0a8d16f0-…","quantity":10}'
json
{ "ok": true, "requested": 10, "taken": 10, "balance": 148.4,
  "orders": [
    { "order_id": "3caf4533-…", "phone": "09056127239",
      "service_name": "Facebook", "price": 0.2,
      "expires_at": "2026-09-09T04:12:00.000Z" }
  ]}

Mua thêm mã trên đúng số cũ: gửi { "rebuy_order_id": "…" } thay cho service_id.

GET/api/v1/orders?ids=a,b,c

Trạng thái đơn, đã giục sẵn. Bỏ ids thì lấy mọi đơn đang chờ cộng các đơn vừa xong trong 10 phút. Tối đa 200 id mỗi lượt.

json
{ "ok": true, "waiting": 1, "orders": [
  { "order_id": "3caf…", "status": "completed", "phone": "09056127239",
    "otp": "135790", "content": "Ma xac minh cua ban la 135790",
    "price": 0.2, "completed_at": "2026-09-09T03:55:12.000Z" },
  { "order_id": "77b5…", "status": "waiting", "phone": "08021053086",
    "otp": null, "expires_at": "2026-09-09T04:12:00.000Z" }
]}
GET/api/v1/orders/wait?ids=a,b,c&timeout=55

Giữ kết nối tới khi có ít nhất một đơn rời trạng thái waiting, rồi trả về ngay. timeout 1–55 giây, mặc định 30. Hết giờ mà chưa có gì thì vẫn trả 200 kèm timed_out: true — cứ gọi lại là chờ tiếp.

GET/api/v1/orders/{id}

Một đơn, đã giục sẵn.

DELETE/api/v1/orders/{id}

Huỷ đơn chưa có mã, hoàn tiền ngay. Đơn đã có mã thì không huỷ được.

4. Mua số riêng — số của bạn, mọi dịch vụ, nhiều tháng

Khác thuê OTP một lần (một số, một dịch vụ, một mã rồi thôi), số riêng là một số thuộc về bạn trong suốt thời hạn: cần mã của dịch vụ nào cũng lấy được, bao nhiêu lần cũng được, cho tới khi hết hạn. Cùng kệ này còn có tài khoản ngâm sẵn, việc làm tay và mail domain — cùng một bộ đường gọi.

GET/api/v1/products?kind=sim

Kệ hàng. Bỏ kind để lấy cả bốn loại: sim, account, manual, email. price là giá BẠN phải trả.

json
{ "ok": true, "products": [
  { "product_id": "8c1e…", "kind": "sim",
    "group_name": "Sim RAKUTEN - Cá Nhân", "variant_label": "RAKUTEN - 3 tháng",
    "price": 14.9, "list_price": 14.9, "duration_days": 90,
    "max_quantity": 1, "in_stock": true }
]}
POST/api/v1/products/orders

Mua. Số riêng trả về phone và expires_at ngay lập tức — từ giây đó số là của bạn.

bash
curl -X POST https://www.jp-otp.com/api/v1/products/orders \
  -H "Authorization: Bearer jp_khoacuaban" \
  -H "Content-Type: application/json" \
  -d '{"product_id":"8c1e…","quantity":1}'
json
{ "ok": true, "balance": 85.1,
  "order": { "order_id": "3f9a…", "kind": "sim", "status": "delivered",
             "phone": "07083743495", "expires_at": "2026-12-10T03:21:00.000Z",
             "amount": 14.9 } }

Món needs_input: true (reg hộ, chuyển hộ…) thì gửi kèm note — link, tên tài khoản, yêu cầu. Những đơn đó về pending, người thật làm xong thì delivered có nội dung.

GET/api/v1/rentals/{order_id}/wait?after_seq=N&timeout=55

Giữ kết nối tới khi số riêng có tin mới rồi trả về ngay. Đây là cách lấy mã trên số riêng. Không truyền after_seq thì chỉ chờ tin MỚI từ lúc gọi.

javascript
// Mua một số riêng, rồi canh mã trên nó
const mua = await fetch(`${GOC}/api/v1/products/orders`, {
  method: 'POST', headers,
  body: JSON.stringify({ product_id: 'ID_SO_RIENG', quantity: 1 }),
}).then(r => r.json());

const id = mua.order.order_id;
console.log('So cua ban:', mua.order.phone, 'toi', mua.order.expires_at);

let seq = 0;                       // 0 = lấy cả tin đã về từ lúc mua
for (;;) {
  const r = await fetch(
    `${GOC}/api/v1/rentals/${id}/wait?after_seq=${seq}&timeout=55`,
    { headers }
  ).then(r => r.json());

  for (const m of r.messages) console.log(m.service_name, m.otp, m.content);
  seq = r.last_seq;                // đẩy con trỏ, không nhận lại tin cũ
}
GET/api/v1/rentals/{order_id}/messages?after_seq=N

Bản hỏi-rồi-trả-ngay của /wait: mọi tin về số đó kể từ lúc mua (hoặc từ after_seq), mới nhất trước, tối đa 200.

GET/api/v1/products/orders?kind=sim

Các số riêng của bạn kèm expires_at. ?ids=a,b,c để hỏi đúng vài đơn.

DELETE/api/v1/products/orders/{id}

Huỷ đơn làm tay còn pending, hoàn tiền. Số riêng và mail đã giao thì không huỷ được.

Tin về số riêng chỉ tính từ lúc bạn mua tới lúc hết hạn. Tin cũ của số đó trước khi bạn mua không lộ ra cho bạn, và tin về sau khi hết hạn cũng không — số đã có thể sang tay người khác.

5. Giới hạn tần suất

Mỗi khoá có một “gáo nước”: mặc định chứa 120 lượt và được rót thêm 5 lượt mỗi giây. Mỗi lượt gọi múc một lượt ra; POST /orders múc 5 lượt vì nó khoá cả nắm SIM trong suốt giao dịch.

Cách này cho phép gọi dồn một nhúm lượt liền nhau — đúng kiểu mua 30 số rồi hỏi mã ngay — mà vẫn chặn được ai gọi dày liên tục. Script bình thường hỏi mã mỗi 2 giây chỉ tiêu cỡ 0,5 lượt/giây, cách trần rất xa. Dùng /orders/wait thì càng rẻ: chờ 55 giây chỉ tốn đúng một lượt.

Câu trả lời nào cũng kèm ba header để script tự biết mà giãn nhịp:

http
X-RateLimit-Limit: 120        sức chứa của gáo
X-RateLimit-Remaining: 118    còn bao nhiêu lượt
X-RateLimit-Refill: 5         rót thêm mỗi giây

Hết nước thì trả 429 kèm Retry-After (số giây phải chờ). Thư viện HTTP nào biết điều cũng tự đọc header đó, không thì đọc tay:

javascript
const r = await fetch(url, { headers });

if (r.status === 429) {
  const cho = Number(r.headers.get('Retry-After') || 5);
  await nghi(cho * 1000);
  continue;                       // roi thu lai
}
Chạm 429 gần như luôn là dấu hiệu script đang hỏi dày hơn mức có ích. Trước khi xin nâng trần, kiểm lại hai chỗ: có đang hỏi từng đơn một thay vì hỏi cả danh sách không, và có dùng /orders/wait chưa. Sửa hai chỗ đó thường là giảm được vài chục lần số lượt gọi.

Cần mức cao hơn thật thì nhắn quản trị viên — mức đặt riêng được cho từng khoá.

6. Trạng thái đơn

waitingĐang chờ mã. Tiền đã trừ.
completedĐã có mã, nằm ở otp. Nội dung tin đầy đủ ở content.
expiredHết hạn mà không có mã. Tiền đã tự hoàn về ví.
cancelledBạn tự huỷ. Tiền đã hoàn.
deliveredHàng bán thêm đã giao: số riêng (phone), tài khoản / mail (delivered), việc làm tay đã xong.
pending / processingViệc làm tay đang chờ / đang làm. Còn huỷ được khi pending.
refundedĐơn hàng bán thêm bị hoàn tiền (hết hàng ở nguồn, hoặc nhân viên từ chối).

7. Mã lỗi

NO_API_KEY401 — chưa gửi header khoá.
BAD_API_KEY401 — khoá sai, đã bị thu hồi, hoặc tài khoản bị khoá.
RATE_LIMITED429 — gọi quá dày. Chờ số giây ghi trong header Retry-After rồi thử lại.
OUT_OF_STOCK409 — hết số khả dụng cho dịch vụ đó. Ví không bị trừ đồng nào.
INSUFFICIENT_BALANCE400 — ví không đủ cho dù chỉ một số.
BAD_QUANTITY400 — quantity phải là số nguyên từ 1 tới 30.
BAD_IDS400 — ids sai định dạng, rỗng, hoặc quá 200 phần tử.
MISSING_PRODUCT / BAD_KIND400 — thiếu/sai product_id, hoặc kind không phải sim/account/manual/email.
INPUT_REQUIRED400 — món này cần note (xem input_label).
MAIL_UNAVAILABLE502 — nguồn mail không tạo được hộp thư lúc này. Tiền đã hoàn.
ORDER_NOT_FOUND404 — không có đơn đó, hoặc đơn không phải của bạn.

Bắt lỗi bằng code, đừng so chuỗi error — chữ tiếng Việt có thể sửa cho dễ đọc hơn bất cứ lúc nào, còn mã thì giữ nguyên.

Còn vướng chỗ nào thì nhắn cho quản trị viên, kèm order_id để tra cho nhanh.