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á đ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.
curl -H "Authorization: Bearer jp_khoacuaban" \
https://www.jp-otp.com/api/v1/balanceKhô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
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
// ĐỪ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.
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
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
- Mua cả nắm trong một lượt gọi.
quantity: 30chạ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. - Hỏi cả danh sách, đừng hỏi từng đơn. Một lượt gọi
?ids=a,b,cgiụ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. - Dùng
/waitthay 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. - Bỏ đơn đã xong ra khỏi danh sách chờ. Nếu vẫn truyền id đã có mã,
/waitthấ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.
/api/v1/balanceVí, hạng và đơn vị tiền của tài khoản.
{ "ok": true, "username": "huygt", "balance": 152.4,
"currency": "USD", "tier": "ctv" }/api/v1/servicesDanh 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.
{ "ok": true, "services": [
{ "service_id": "0a8d16f0-…", "service_name": "Facebook",
"list_price": 0.5, "price": 0.2 }
]}/api/v1/ordersMua 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.
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}'{ "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.
/api/v1/orders?ids=a,b,cTrạ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.
{ "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" }
]}/api/v1/orders/wait?ids=a,b,c&timeout=55Giữ 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.
/api/v1/orders/{id}Một đơn, đã giục sẵn.
/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.
/api/v1/products?kind=simKệ hàng. Bỏ kind để lấy cả bốn loại: sim, account, manual, email. price là giá BẠN phải trả.
{ "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 }
]}/api/v1/products/ordersMua. Số riêng trả về phone và expires_at ngay lập tức — từ giây đó số là của bạn.
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}'{ "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.
/api/v1/rentals/{order_id}/wait?after_seq=N&timeout=55Giữ 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.
// 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ũ
}/api/v1/rentals/{order_id}/messages?after_seq=NBả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.
/api/v1/products/orders?kind=simCác số riêng của bạn kèm expires_at. ?ids=a,b,c để hỏi đúng vài đơn.
/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.
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:
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âyHế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:
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
}/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. |
expired | Hết hạn mà không có mã. Tiền đã tự hoàn về ví. |
cancelled | Bạn tự huỷ. Tiền đã hoàn. |
delivered | Hàng bán thêm đã giao: số riêng (phone), tài khoản / mail (delivered), việc làm tay đã xong. |
pending / processing | Việ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_KEY | 401 — chưa gửi header khoá. |
BAD_API_KEY | 401 — khoá sai, đã bị thu hồi, hoặc tài khoản bị khoá. |
RATE_LIMITED | 429 — gọi quá dày. Chờ số giây ghi trong header Retry-After rồi thử lại. |
OUT_OF_STOCK | 409 — hết số khả dụng cho dịch vụ đó. Ví không bị trừ đồng nào. |
INSUFFICIENT_BALANCE | 400 — ví không đủ cho dù chỉ một số. |
BAD_QUANTITY | 400 — quantity phải là số nguyên từ 1 tới 30. |
BAD_IDS | 400 — ids sai định dạng, rỗng, hoặc quá 200 phần tử. |
MISSING_PRODUCT / BAD_KIND | 400 — thiếu/sai product_id, hoặc kind không phải sim/account/manual/email. |
INPUT_REQUIRED | 400 — món này cần note (xem input_label). |
MAIL_UNAVAILABLE | 502 — nguồn mail không tạo được hộp thư lúc này. Tiền đã hoàn. |
ORDER_NOT_FOUND | 404 — 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.