v1 ổn định

API đại lý

Bán proxy cho khách của bạn qua web, bot hay tool riêng: tự tạo key con, giao chuỗi proxy, đổi IP hộ khách, gia hạn và thu hồi có hoàn tiền. Khách của bạn không cần mở tài khoản ở IP2.VN.

Địa chỉ gốc và token

Mọi endpoint đại lý bắt đầu bằng địa chỉ dưới đây, chỉ nhận HTTPS, trả về JSON có ok.

https://api.ip2.vn/v1/reseller

Xác thực bằng token đại lý dạng rsl_…, gửi ở header của mọi lời gọi. Lời gọi có thân JSON thì kèm thêm Content-Type: application/json.

Authorization: Bearer rsl_xxxxxxxxxxxx

Lấy token: lên bậc Đại lý (ví chính có từ 5.000.000đ là tự bấm nâng bậc ở trang Tài khoản, máy xét ngay, không trừ tiền), rồi vào bảng điều khiển, mục API của tôi, khối Token đại lý, bấm tạo. Token chỉ hiện đúng một lần lúc tạo — chép cất ngay; mất thì thu hồi token cũ và tạo token mới.

Mọi token và key trong trang này đều là chuỗi ví dụ. rsl_xxxxxxxxxxxx và ip2_9f8e7d6c5b4a chỉ để cho thấy hình dạng — gọi nguyên như trong tài liệu sẽ nhận invalid_token.

Các endpoint

Chỉ mở cho tài khoản bậc Đại lý — ví chính có từ 5.000.000đ là tự bấm nâng bậc ở trang Tài khoản, máy xét ngay, không trừ tiền. Dùng token riêng ở cấp tài khoản chứ không phải key của từng port, cho phép bạn tự tạo và quản lý key con để bán lại.

Đây là nhóm duy nhất mua được port qua API. Token tài khoản thường cố ý không có quyền đó: lộ token thì mất quyền điều khiển port chứ không mất tiền trong ví. Muốn dựng web bán proxy của riêng mình thì xem Bán trên web của bạn.

Cấp token đại lý cần số dư ví chính từ 5.000.000đ trở lên. Mỗi key con trừ tiền ngay lúc tạo, nên phải có sẵn vốn thì lượt bán đầu tiên mới không báo hết tiền cho khách của bạn. Token đã cấp vẫn chạy bình thường khi số dư tụt xuống dưới mức đó.

POST/v1/reseller/keyscần token đại lý
Authorization: Bearer rsl_xxxxxxxxxxxx POST /v1/reseller/keys { "line": "S1", "days": 30, "shift": "ca_24h", "quantity": 1, "auto_renew": true, "note": "khach-abc" } { "ok": true, "key": "ip2_9f8e7d6c5b4a", "port": 20007, "line": "S1", "expire_at": "2026-10-04T23:59:59+07:00", "charged": 189600 }

Các endpoint khác

EndpointViệc
GET /v1/reseller/keysLiệt kê mọi key con bạn đã tạo, kèm hạn dùng
GET /v1/reseller/keys/:idXem lại đủ một key con: key, link đổi IP, mật khẩu proxy
POST /v1/reseller/rotateĐổi IP một key con bằng token đại lý (id, wait)
POST /v1/reseller/renewGia hạn một key con
POST /v1/reseller/auto-renewBật/tắt tự gia hạn một key con (id, auto_renew, days)
GET /v1/reseller/loc-ten-mienXem bộ lọc traffic của một key con (id qua query)
POST /v1/reseller/loc-ten-mienThêm một tên miền vào bộ lọc (id, domain) — tối đa 3 tên mỗi cổng
DELETE /v1/reseller/loc-ten-mienBỏ một tên miền khỏi bộ lọc (id, domain)
POST /v1/reseller/loc-khoLọc hai kho cho một key con (id, kho1_giay, kho2) — kho 1 tránh IP đã dùng, kho 2 hỏi API ngoài
POST /v1/reseller/kho-ipBật/tắt kho IP riêng 24 giờ cho một key con (id, bat)
POST /v1/reseller/auto-rotateHẹn giờ tự đổi IP một key con (id, every — số giây, 0 là tắt)
DELETE /v1/reseller/keys/:idĐã bỏ — trả 410 da_bo_thu_hoi, key mua rồi dùng tới hết hạn
GET /v1/reseller/stockXem line nào còn slot trước khi bán
Mỗi port chỉ dùng cho một người. Nếu hệ thống thấy một key có quá nhiều IP nguồn khác nhau kết nối vào, key sẽ bị tạm khóa và chúng tôi liên hệ với bạn.
Lên đại lý

Bán trên web của bạn

Năm bước là đủ để dựng một cửa hàng proxy của riêng bạn. Khách bấm mua trên web của bạn, web của bạn gọi sang đây, nhận về chuỗi proxy rồi giao thẳng cho họ — không ai phải mở tài khoản ở IP2.VN.

Bước 1 — bày hàng

Hỏi kho trước khi cho khách bấm mua, để đừng bán thứ không còn.

GET /v1/reseller/stock { "ok": true, "tong_con_trong": 27, "lines": [ { "line": "S1", "con_trong": 14 }, { "line": "S2", "con_trong": 13 } ] }

Bước 2 — khách bấm mua

Một lời gọi làm trọn gói: chọn port trống, trừ ví của bạn theo bảng giá, sinh tài khoản proxy, báo xuống máy chạy port, rồi trả về đủ thứ để giao cho khách.

POST /v1/reseller/keys { "line": "S1", "days": 30, "shift": "ca_24h", "quantity": 1, "auto_renew": true, "note": "khach-abc" } { "ok": true, "key": "ip2_9f8e7d6c5b4a", "host": "s1.poolviettel.com", "port": 20007, "line": "S1", "proxy_user": "ip2a1b2c3d4", "proxy_pass": "K3nqR7xB2mQ", "shift": "ca_24h", "expire_at": "2026-10-04T23:59:59+07:00", "charged": 189600, "rental_id": "3f2a…", "auto_renew": true } # chuỗi giao cho khách của bạn http://ip2a1b2c3d4:K3nqR7xB2mQ@s1.poolviettel.com:20007

Nhớ rental_id vào cơ sở dữ liệu của bạn, gắn với đơn hàng — mọi lệnh về sau đều cần nó. Trường charged là số tiền bị trừ khỏi ví bạn, so với giá bạn bán ra chính là phần lời của đơn đó.

Bán nhiều port một lượt

Đặt "quantity" từ 2 tới 50 để tạo cả loạt key con trong một lời gọi. Ví bị trừ một lần theo giá bậc gộp của cả loạt, và mọi key nằm trong mảng items. Kho không đủ số lượng thì nhận out_of_stock — không trừ tiền, không cấp key nào.

POST /v1/reseller/keys { "line": "S1", "days": 30, "quantity": 10, "note": "don-123" } { "ok": true, "quantity": 10, "charged": 1540500, "items": [ { "key": "ip2_9f8e7d6c5b4a", "host": "s1.poolviettel.com", "port": 20007, "line": "S1", "proxy_user": "ip2a1b2c3d4", "proxy_pass": "K3nqR7xB2mQ", "shift": "ca_24h", "expire_at": "2026-10-15T10:00:00.000Z", "rental_id": "3f2a…" }, … ] }

quantity bằng 1 hoặc bỏ trống thì kết quả giữ nguyên dạng một key như trên (có thêm quantity và items), nên code cũ của bạn không phải sửa. Viết mới thì đọc items là chạy cho mọi trường hợp.

Mua ca ngày / ca đêm: gửi "shift": "ca_ngay" (8h–20h) hoặc "ca_dem" (20h–8h) với "days": 1 — ví dụ { "days": 1, "shift": "ca_ngay", "quantity": 5 }. Chỉ gọi được trong đúng khung giờ của ca.

Bước 3 — khách đổi IP

Mỗi key con là một port có IP riêng, đổi IP không giới hạn số lần. Có hai cách, chọn cách hợp với web của bạn. Cả hai dùng chung một đồng hồ giãn cách: hai lần đổi IP của cùng một port phải cách nhau ít nhất 180 giây, dù gọi bằng lối nào.

Cách 1 — giao key cho khách. Trường key ở bước 2 là key của riêng port đó. Đưa khách link đổi IP dưới đây: họ gọi link đó từ script hoặc code của họ. Với key đó khách còn dùng được cả nhóm API dùng key: /v1/info, /v1/auto hẹn giờ tự xoay, /v1/history.

# link đổi IP giao cho khách https://api.ip2.vn/v1/rotate?key=ip2_9f8e7d6c5b4a

Cách 2 — web của bạn đổi IP hộ. Giữ key ở phía bạn; khách bấm nút "đổi IP" trên web bạn thì web gọi bằng token đại lý, với id là rental_id đã lưu ở bước 2:

POST/v1/reseller/rotatecách nhau tối thiểu 180 giây
POST /v1/reseller/rotate { "id": "3f2a…", "wait": true } { "ok": true, "id": "3f2a…", "ip": "113.161.201.7", "previous_ip": "113.161.94.28", "host": "s1.poolviettel.com", "port": 20007, "line": "S1", "took": 31.6, "next_allowed_in": 180 }

wait mặc định là true: chờ tới khi port ra IP mới rồi mới trả — thường 20–45 giây, tối đa 90 giây, nên đặt hạn chờ phía bạn từ 100 giây. "wait": false thì trả về ngay sau khi đẩy lệnh, IP mới hỏi lại bằng GET /v1/reseller/keys/:id. Gọi sớm hơn 180 giây là 429 cooldown kèm retry_after; lượt trước còn đang quay là 429 rotate_dang_chay.

Lấy lại key hoặc mật khẩu đã mất

GET /v1/reseller/keys/3f2a… { "ok": true, "id": "3f2a…", "key": "ip2_9f8e7d6c5b4a", "link_doi_ip": "https://api.ip2.vn/v1/rotate?key=ip2_9f8e7d6c5b4a", "host": "s1.poolviettel.com", "port": 20007, "line": "S1", "proxy_user": "ip2a1b2c3d4", "proxy_pass": "K3nqR7xB2mQ", "ip": "113.161.201.7", "expire_at": "2026-10-04T16:59:59.000Z" }

Danh sách GET /v1/reseller/keys cố ý không mang key đầy đủ và mật khẩu — một lượt gọi lộ cả kho — nên lấy lại từng key con theo id. Key con tạo trước ngày 14/09/2026 có thể trả "key": null; port đó vẫn đổi IP được bằng cách 2.

Bước 4 — khách gia hạn

POST /v1/reseller/renew { "id": "3f2a…", "days": 30, "idempotency_key": "gia-han-don-123" } { "ok": true, "days_added": 30, "charged": 189600, "shift": "ca_24h", "chuyen_sang_24h": false, "expire_at": "…" }

Hạn mới cộng dồn từ hạn cũ, không phải từ lúc bấm — khách gia hạn sớm không mất ngày nào. Key ca ngày / ca đêm cũng gia hạn được: tính theo ngày và chuyển sang ca 24 giờ (chuyen_sang_24h). Cùng giá, cùng luật với khách tự gia hạn trên web, và máy chạy port nhận hạn mới ngay.

Gọi lại an toàn: gửi kèm idempotency_key (chuỗi 8–100 ký tự do bạn đặt, ví dụ mã đơn) — rớt mạng rồi gọi lại với cùng khoá thì chỉ bị trừ tiền một lần, lần sau trả lại đúng kết quả lần trước.

Tự gia hạn — bật hay tắt theo đơn của khách

Tới hạn mà key con đang bật tự gia hạn thì hệ thống tự gia hạn và trừ ví của bạn; đang tắt thì key bị thu hồi ngay, port về kho. Mặc định: ca 24 giờ bật, ca ngày / ca đêm tắt. Khách của bạn thôi trả tiền thì tắt ngay, không thì ví bạn vẫn bị trừ mỗi kỳ.

POST/v1/reseller/auto-renewcần token đại lý
POST /v1/reseller/auto-renew { "id": "3f2a…", "auto_renew": false } { "ok": true, "id": "3f2a…", "auto_renew": false, "auto_renew_days": 1 } # bật lại, mỗi lần tự gia hạn thêm 7 ngày { "id": "3f2a…", "auto_renew": true, "days": 7 }

days nhận 1, 7 hoặc 30 (mặc định 1) — số ngày mỗi lượt tự gia hạn, cùng giá như gia hạn tay. Đặt luôn lúc bán bằng "auto_renew": false trong POST /v1/reseller/keys. Trạng thái hiện ở auto_renew và auto_renew_days của GET /v1/reseller/keys. Key ca lẻ không bật được (ca_ngay_khong_gia_han) — gia hạn bằng /renew một lần cho thành ca 24 giờ rồi bật.

Hẹn giờ tự đổi IP

POST /v1/reseller/auto-rotate { "id": "3f2a…", "every": 900 } { "ok": true, "id": "3f2a…", "auto": true, "every": 900, "next_at": "2026-09-18T14:15:00.000Z" }

Đừng nhầm với tự gia hạn ở trên. auto-renew là chuyện tiền — tới hạn thì trừ ví bạn để giữ port. auto-rotate là chuyện IP — cứ every giây thì đổi IP một lần, không tốn đồng nào.

every là số giây giữa hai lượt xoay, 0 là tắt, thấp nhất 180 giây (dưới mức đó trả invalid_every). Xem trạng thái ở auto_every và auto_next_at trong GET /v1/reseller/keys.

Khách của bạn cũng tự bật được bằng key ip2_… của chính họ qua POST /v1/auto — cùng một cơ chế, cùng một trần.

Bộ lọc traffic 24 giờ

Chọn tên miền cho một key con. Xoay xong, cổng sẽ không nhận những IP mà bất kỳ cổng nào trong hệ thống đã dùng để vào tên miền đó trong 24 giờ qua — bên kia nhận ra IP chứ không nhận ra ai thuê nó.

# xem bộ lọc hiện tại (id gửi qua query vì đây là lượt đọc) GET /v1/reseller/loc-ten-mien?id=3f2a… { "ok": true, "data": { "items": [ { "domain": "tiktok.com", "so_ip_tranh": 12 } ], "toi_da": 3 } } # thêm một tên miền POST /v1/reseller/loc-ten-mien { "id": "3f2a…", "domain": "tiktok.com" } # bỏ một tên miền DELETE /v1/reseller/loc-ten-mien { "id": "3f2a…", "domain": "tiktok.com" }

Tối đa 3 tên miền mỗi cổng, và trần đó cố ý để thấp: lọc càng nhiều thì càng nhiều IP bị loại, mà node quay tới khi ra IP sạch mới thôi — cái giá đó khách của bạn trả bằng thời gian chờ. Nên bật cho key nào thật sự cần. so_ip_tranh cho biết mỗi tên miền hiện đang khiến bao nhiêu IP bị tránh, để bạn thấy nút có tác dụng thật.

Chưa chọn tên miền nào vẫn trả ok: true với danh sách rỗng — đó là trạng thái hợp lệ, không phải lỗi.

Kho IP riêng 24 giờ

POST /v1/reseller/kho-ip { "id": "3f2a…", "bat": true } { "ok": true, "data": { "id": "3f2a…", "tranh_ip_24h": true } }

Bật thì lệnh xoay mang theo danh sách IP mà chính cổng đó đã dùng trong 24 giờ, và node quay tiếp khi tổng đài cấp lại trúng một trong số đó. Tổng đài Viettel cấp lại IP cũ là chuyện bình thường của mạng dân cư; đây là cách quay giùm khách thay vì để họ tự bấm lại.

Khác với bộ lọc traffic ở trên: kho IP chỉ nhìn lịch sử của một cổng, còn bộ lọc nhìn IP nào đã vào một tên miền trên toàn hệ thống. Bật cả hai cũng được, và khi ấy thời gian chờ cộng lại.

Bước 5 — khách thôi dùng

DELETE /v1/reseller/keys/3f2a… { "ok": false, "error": "da_bo_thu_hoi", "message": "Đã bỏ thu hồi key con…" }

Tính năng này đã bỏ từ 18/09/2026. Key mua rồi thì dùng tới hết hạn — không trả lại, không hoàn tiền. Gọi đường cũ sẽ nhận 410 kèm mã da_bo_thu_hoi.

Không muốn giữ key nữa thì tắt tự gia hạn bằng POST /v1/reseller/auto-renew: tới hạn key tự về kho và ví bạn không bị trừ thêm lượt nào.

Tiền lời nằm ở đâu

Bạn mua port bằng đúng giá khách lẻ, không rẻ hơn một đồng. Phần lời nằm ở lượt nạp: mỗi lượt nạp từ 1.000.000đ của đại lý được cộng thêm 30% — chuyển khoản 10.000.000đ thì ví nhận 13.000.000đ. Bán lại theo bảng giá công khai là bạn ăn trọn phần chênh đó.

Ca lẻ chỉ bán được trong khung giờ của nó. Gửi thêm "shift": "ca_ngay" hoặc "ca_dem" ở bước 2 (bỏ trống là ca_24h), days phải bằng 1. Ca ngày 8h–20h, ca đêm 20h–8h, mỗi ca giá bằng 60% một ngày và hết ca là hết — gọi ngoài khung giờ sẽ nhận ngoai_khung_gio. Gia hạn một key ca lẻ chính là chuyển nó thành ca 24 giờ.
Ví phải có sẵn tiền. Mỗi lời gọi ở bước 2 trừ ví ngay lúc gọi. Hết tiền giữa chừng là insufficient_funds, khách của bạn bấm mua mà không nhận được gì — nên web của bạn nên kiểm số dư trước, hoặc bắt lỗi đó và báo lại tử tế.

Mã lỗi

Lỗi luôn trả về ok: false kèm error dạng chữ và message tiếng Việt để bạn hiện thẳng cho khách.

{ "ok": false, "error": "out_of_stock", "message": "Máy S1 không còn đủ port trống." }
MãerrorNghĩa
401invalid_tokenToken đại lý sai hoặc đã bị thu hồi
403not_resellerTài khoản chưa ở bậc Đại lý
403account_suspendedTài khoản đang bị khoá
400so_du_khong_duLúc tạo token mà ví chính chưa đủ 5.000.000đ
402insufficient_fundsVí chính không đủ tiền để tạo hoặc gia hạn key con
409out_of_stockMáy được chọn đã hết port trống, hoặc không đủ số lượng xin — không trừ tiền, không cấp key nào
400invalid_daysdays chỉ nhận 1, 7 hoặc 30
400invalid_quantityquantity phải từ 1 tới 50
400ca_ngay_mot_caCa ngày / ca đêm chỉ bán days = 1
400ngoai_khung_gioTạo ca lẻ ngoài khung giờ của ca (ca ngày 8h–20h, ca đêm 20h–8h)
404key_not_foundKhông tìm thấy key con (sai id, không phải của bạn, hoặc đã thu hồi)
404not_foundKhông tìm thấy token khi thu hồi token
400ca_ngay_khong_gia_hanBật tự gia hạn cho key ca ngày / ca đêm — hết ca là hết; gia hạn bằng /renew một lần cho thành ca 24 giờ rồi bật
409expiredKey con đã hết hạn — gia hạn bằng /renew rồi mới đổi IP được
429cooldownChưa đủ 180 giây kể từ lần đổi IP trước (tính chung mọi lối) — chờ đúng số giây trong retry_after
429rotate_dang_chayLượt đổi IP trước còn đang quay — đợi nó xong, đừng gửi chồng
503line_downMáy giữ port mất liên lạc nên lệnh đổi IP không gửi xuống được; hệ thống tự chuyển port sang máy khác — gọi GET /v1/reseller/keys/:id lấy host, port mới

Ví dụ hoàn chỉnh

Một cửa hàng tối giản: xem kho, bán một port 30 ngày, giao chuỗi proxy, và đổi IP khi khách bấm nút — xử lý sẵn cả trường hợp gọi đổi IP quá sớm.

cua_hang.py
import requests, time API = "https://api.ip2.vn/v1/reseller" H = {"Authorization": "Bearer rsl_xxxxxxxxxxxx"} def ban(ma_don): kho = requests.get(f"{API}/stock", headers=H).json() if kho["tong_con_trong"] == 0: raise Exception("Hết hàng") r = requests.post(f"{API}/keys", headers=H, json={ "days": 30, "shift": "ca_24h", "quantity": 1, "note": ma_don}).json() if not r["ok"]: raise Exception(r["message"]) # lưu r["rental_id"] vào đơn hàng — đổi IP, gia hạn, thu hồi đều cần nó proxy = f"http://{r['proxy_user']}:{r['proxy_pass']}@{r['host']}:{r['port']}" return r["rental_id"], proxy def doi_ip(rental_id): r = requests.post(f"{API}/rotate", headers=H, json={"id": rental_id}, timeout=100).json() if not r["ok"]: if r["error"] == "cooldown": time.sleep(r["retry_after"]) return doi_ip(rental_id) raise Exception(r["message"]) return r["ip"] rental_id, proxy = ban("don-123") print(proxy, doi_ip(rental_id))
cua-hang.mjs
const API = "https://api.ip2.vn/v1/reseller"; const H = { Authorization: "Bearer rsl_xxxxxxxxxxxx", "Content-Type": "application/json" }; async function ban(maDon) { const r = await fetch(`${API}/keys`, { method: "POST", headers: H, body: JSON.stringify({ days: 30, shift: "ca_24h", quantity: 1, note: maDon }) }).then(x => x.json()); if (!r.ok) throw new Error(r.message); // lưu r.rental_id vào đơn hàng return { id: r.rental_id, proxy: `http://${r.proxy_user}:${r.proxy_pass}@${r.host}:${r.port}` }; } async function doiIp(id) { const r = await fetch(`${API}/rotate`, { method: "POST", headers: H, body: JSON.stringify({ id }) }).then(x => x.json()); if (!r.ok && r.error === "cooldown") { await new Promise(ok => setTimeout(ok, r.retry_after * 1000)); return doiIp(id); } if (!r.ok) throw new Error(r.message); return r.ip; } const don = await ban("don-123"); console.log(don.proxy, await doiIp(don.id));
terminal
# máy nào còn port trống curl https://api.ip2.vn/v1/reseller/stock -H "Authorization: Bearer rsl_xxxxxxxxxxxx" # bán một port 30 ngày curl -X POST https://api.ip2.vn/v1/reseller/keys -H "Authorization: Bearer rsl_xxxxxxxxxxxx" \ -H "Content-Type: application/json" -d '{"line":"S1","days":30,"shift":"ca_24h","quantity":1,"note":"don-123"}' # đổi IP hộ khách (id = rental_id), chờ xoay xong curl -X POST https://api.ip2.vn/v1/reseller/rotate -H "Authorization: Bearer rsl_xxxxxxxxxxxx" \ -H "Content-Type: application/json" -d '{"id":"3f2a…"}' --max-time 100 # lấy lại key, link đổi IP, mật khẩu proxy curl https://api.ip2.vn/v1/reseller/keys/3f2a… -H "Authorization: Bearer rsl_xxxxxxxxxxxx"