POST /apiv2/bandwidth
Thuê Bandwidth TRON và ủy quyền (delegate) cho một địa chỉ người nhận trong một khoảng thời gian cố định (5 phút hoặc 1 giờ).
⚠️ Các hạng mức truy cập.
- Tài khoản được kiểm định (accredited) có thể thuê bất kỳ số lượng nào (tối đa 5000) trong giới hạn kích thước pool và mức tối đa, với nhiều đơn hàng đồng thời. Quyền kiểm định được cấp bởi bộ phận hỗ trợ của Netts.
- Không có kiểm định, bạn chỉ có thể thuê 400 đơn vị một lần — đơn hàng tiếp theo chỉ được phép thực hiện sau khi lượt thuê trước kết thúc. Các yêu cầu cho số lượng khác 400, hoặc đơn hàng thứ hai trong khi đơn đầu tiên vẫn đang hoạt động, sẽ bị từ chối.
URL Điểm cuối
POST https://netts.io/apiv2/bandwidthTiêu đề Yêu cầu
| Tiêu đề | Bắt buộc | Mô tả |
|---|---|---|
| Content-Type | Có | application/json |
| X-API-KEY | Có | Khóa API của bạn từ bảng điều khiển Netts |
| X-Real-IP | Có | Địa chỉ IP từ danh sách trắng (whitelist) của bạn |
| X-Idempotency-Key | Không | Khóa tùy chọn do máy khách tạo (base64) để thử lại an toàn mà không bị trùng lặp đơn hàng. Nếu bỏ qua, máy chủ sẽ tự động tạo một khóa |
Thân Yêu cầu
{
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m"
}Tham số
| Tham số | Loại | Bắt buộc | Mô tả |
|---|---|---|---|
| amount | số nguyên | Có | Số lượng đơn vị Bandwidth cần thuê (tối thiểu: 400, tối đa: 5000) |
| receiveAddress | chuỗi | Có | Địa chỉ TRON sẽ nhận Bandwidth (T…, 34 ký tự, base58) |
| period | chuỗi | Có | Thời hạn thuê: "5m" (5 phút) hoặc "1h" (1 giờ) |
| trx_send | boolean | Không | Giao dịch đảm bảo: nếu không có sẵn Bandwidth, gửi TRX đến địa chỉ thay thế để giao dịch vẫn được thực hiện. Chỉ hoạt động khi amount = 400 (bị bỏ qua trong các trường hợp khác). Mặc định là false |
| check | boolean | Không | Nếu là true và người nhận đã có nhiều hơn 400 Bandwidth, đơn hàng sẽ không được ủy quyền và không bị tính phí (trạng thái enough). Mặc định là false |
| test | boolean | Không | Chạy thử (dry run). Nếu là true, toàn bộ quy trình đơn hàng sẽ được mô phỏng — phản hồi sẽ cho bạn biết kết quả sẽ diễn ra và mức giá sẽ bị tính phí — mà không thực hiện bất kỳ hành động nào trên chuỗi và không tính phí. Mặc định là false |
Yêu cầu Mẫu
Các ví dụ bên dưới cũng tạo và gửi
X-Idempotency-Keyđể việc gửi lặp lại vô tình không tạo ra đơn hàng thứ hai. Xem phần Tính bất biến để biết đầy đủ các quy tắc.
cURL
API_KEY="your_api_key"
ADDR="TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
AMOUNT=1500
PERIOD="5m"
NONCE=$(( $(date +%s) / 2 )) # stable for retries within a 2s window; or your own order UUID
# X-Idempotency-Key = base64( HMAC-SHA256( API_KEY, "addr:amount:period:nonce" ) )
IDEMP=$(printf '%s' "${ADDR}:${AMOUNT}:${PERIOD}:${NONCE}" \
| openssl dgst -sha256 -hmac "$API_KEY" -binary | base64)
curl -X POST https://netts.io/apiv2/bandwidth \
-H "Content-Type: application/json" \
-H "X-API-KEY: $API_KEY" \
-H "X-Real-IP: your_whitelisted_ip" \
-H "X-Idempotency-Key: $IDEMP" \
-d "{\"amount\": $AMOUNT, \"receiveAddress\": \"$ADDR\", \"period\": \"$PERIOD\"}"Python
import time, hmac, hashlib, base64, requests
API_KEY = "your_api_key"
url = "https://netts.io/apiv2/bandwidth"
payload = {
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m",
}
# X-Idempotency-Key = base64( HMAC-SHA256( API_KEY, "addr:amount:period:nonce" ) )
# Generate ONCE per order and resend the same value on every retry.
nonce = str(int(time.time() // 2)) # 2s bucket; or your own order UUID
message = f"{payload['receiveAddress']}:{payload['amount']}:{payload['period']}:{nonce}"
idem_key = base64.b64encode(
hmac.new(API_KEY.encode(), message.encode(), hashlib.sha256).digest()
).decode()
headers = {
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
"X-Real-IP": "your_whitelisted_ip",
"X-Idempotency-Key": idem_key,
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
detail = data.get("detail", {})
if response.status_code == 200 and detail.get("status") == "completed":
d = detail["data"]
print(f"Order ID: {d['orderId']}")
print(f"Hashes: {d['hash']}") # array of delegation tx hashes
print(f"Bandwidth: {d['bandwidth']} for {d['period']}")
print(f"Cost: {d['paidTRX']} TRX")
else:
print(f"Code: {detail.get('code')} | {detail.get('msg', detail)}")Ví dụ đầy đủ cho máy khách (Python + cURL) được cung cấp cùng với gói dịch vụ (handler_bandwidth/doc/client_example/).
Phản hồi
Thành công — Bandwidth đã được ủy quyền (200 OK)
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful",
"data": {
"orderId": "B5M<key14>",
"paidTRX": "<amount charged in TRX>",
"fulfilledBy": "bandwidth",
"hash": ["a1b2c3...", "d4e5f6..."],
"bandwidth": 1500,
"period": "5m"
}
}
}Thành công — TRX được gửi thay cho Bandwidth (200 OK, chỉ áp dụng amount=400 + trx_send=true)
Khi pool không còn Bandwidth và trx_send được bật, TRX sẽ được gửi đến địa chỉ để giao dịch vẫn diễn ra thành công. Một khoản phí cố định sẽ được áp dụng trong trường hợp này, bất kể thời hạn yêu cầu là bao lâu.
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful (sent TRX, bandwidth unavailable)",
"data": {
"orderId": "B5M<key14>",
"paidTRX": "<amount charged in TRX>",
"fulfilledBy": "trx",
"trxSendHash": ["<txid>"],
"hash": [],
"bandwidth": 400,
"period": "5m"
}
}
}Đã có đủ — không tính phí (200 OK, chỉ với check=true)
{
"detail": {
"code": 10002,
"status": "enough",
"msg": "enough band for 1 transfer",
"data": { "orderId": "B5M<key14>", "paidTRX": 0, "bandwidth": 400, "period": "5m" }
}
}Đang xử lý — nhà cung cấp bên ngoài (202 Accepted)
Được trả về khi đơn hàng được chuyển cho nhà cung cấp bên ngoài theo phương thức bất đồng bộ. Thăm dò (poll) điểm cuối trạng thái (bên dưới) bằng orderId cho đến khi hoàn tất.
{
"detail": {
"code": 10001,
"status": "processing",
"msg": "Order accepted, processed by an external provider. Poll the status endpoint.",
"data": { "orderId": "B5M<key14>", "bandwidth": 1500, "period": "5m" }
}
}Chạy thử (200 OK, chỉ với test=true)
Toàn bộ luồng đơn hàng được mô phỏng. testAction cho bạn biết điều gì sẽ xảy ra và wouldCostTRX cho biết số tiền sẽ bị tính phí. Không có gì được ủy quyền, không có TRX nào được gửi, không tính bất kỳ khoản phí nào (paidTRX: 0).
{
"detail": {
"code": 10003,
"status": "test",
"msg": "Test run — no on-chain action, no charge",
"data": {
"orderId": "B5M<...>",
"testAction": "would_delegate",
"wouldCostTRX": "<amount that would be charged in TRX>",
"paidTRX": 0,
"bandwidth": 400,
"period": "5m",
"receiverFreeBandwidth": 600
}
}
}Các giá trị của testAction: would_delegate (Bandwidth sẽ được ủy quyền), would_trx_send (không có Bandwidth, amount=400 + trx_send → TRX sẽ được gửi), enough (người nhận đã có đủ, với check=true), hoặc would_error:<reason> (ví dụ: no_bandwidth, not_whitelisted).
Các Trường Phản hồi
| Trường | Loại | Mô tả |
|---|---|---|
| detail.code | số nguyên | 10000 đã ủy quyền/TRX, 10002 đã đủ, 10001 đang xử lý |
| detail.status | chuỗi | completed / enough / processing / failed |
| detail.data.orderId | chuỗi | ID đơn hàng, định dạng B5M… (5m) / B1H… (1h) — sử dụng giá trị này cho điểm cuối trạng thái |
| detail.data.paidTRX | số | Số tiền bị tính bằng TRX (0 khi enough) |
| detail.data.fulfilledBy | chuỗi | bandwidth (đã ủy quyền) / trx (đã gửi TRX) |
| detail.data.hash | mảng | Các mã băm (hash) giao dịch ủy quyền (tối đa 10). Luôn là một mảng (trống đối với trường hợp TRX) |
| detail.data.trxSendHash | mảng | Mã băm giao dịch chuyển TRX, chỉ xuất hiện khi fulfilledBy = trx |
| detail.data.bandwidth | số nguyên | Số đơn vị Bandwidth đã được ủy quyền |
| detail.data.period | chuỗi | Thời hạn thuê (5m / 1h) |
Điểm cuối Trạng thái
GET https://netts.io/apiv2/bandwidth/status/{orderId}Tiêu đề: X-API-KEY + X-Real-IP (đơn hàng phải thuộc về người dùng đã được xác thực).
| Trạng thái đơn hàng | HTTP | code | status |
|---|---|---|---|
| Đã hoàn thành | 200 | 10000 | completed (với hash / trxSendHash) |
| Đang tiến hành | 200 | 10001 | processing |
| Đã có đủ | 200 | 10002 | enough |
| Thất bại | 200 | 5003 | failed |
| Không tìm thấy / không thuộc sở hữu của bạn | 404 | -1 | — |
Điểm cuối Thu hồi
Chủ động thu hồi (hủy ủy quyền) Bandwidth của một trong các đơn hàng đã ủy quyền của bạn trước khi hết thời hạn. Bandwidth sẽ được tự động hủy ủy quyền và mã băm giao dịch sẽ được trả về.
POST https://netts.io/apiv2/bandwidth/reclaim/{orderId}Tiêu đề: X-API-KEY + X-Real-IP (đơn hàng phải thuộc về người dùng đã được xác thực).
| Trạng thái đơn hàng | HTTP | code | status | Kết quả |
|---|---|---|---|---|
| Đã ủy quyền → thu hồi ngay bây giờ | 200 | 10004 | reclaimed | reclaimHash (mã băm giao dịch hủy ủy quyền) |
| Đã được thu hồi trước đó | 200 | 10004 | reclaimed | reclaimHash + thông báo "already reclaimed" |
| Không ở trạng thái được ủy quyền (không có gì để thu hồi) | 400 | 5005 | failed | — |
| Việc thu hồi vẫn chưa hoàn tất | 503 | 5003 | failed | thử lại sau chốc lát |
| Không tìm thấy / không thuộc sở hữu của bạn | 404 | -1 | — | — |
curl -X POST https://netts.io/apiv2/bandwidth/reclaim/B5M<...> \
-H "X-API-KEY: your_api_key" -H "X-Real-IP: your_whitelisted_ip"{
"detail": {
"code": 10004,
"status": "reclaimed",
"msg": "Bandwidth reclaimed",
"data": { "orderId": "B5M<...>", "reclaimHash": ["<txid>"] }
}
}import requests
order_id = "B5M..." # the orderId from your rental response
url = f"https://netts.io/apiv2/bandwidth/reclaim/{order_id}"
headers = {"X-API-KEY": "your_api_key", "X-Real-IP": "your_whitelisted_ip"}
resp = requests.post(url, headers=headers)
detail = resp.json()["detail"]
if resp.status_code == 200 and detail["status"] == "reclaimed":
print(f"Reclaimed: {detail['data']['reclaimHash']} ({detail['msg']})")
else:
print(f"Code {detail.get('code')}: {detail.get('msg', detail)}")Phí thuê không được hoàn lại khi chủ động thu hồi sớm — việc thu hồi chỉ trả lại Bandwidth đã ủy quyền về pool trước thời hạn.
Phản hồi Lỗi
Lỗi Xác thực (401)
{ "detail": { "code": -1, "msg": "Invalid API key or IP not in whitelist" } }Số dư Không đủ (403)
{ "detail": { "code": 1004, "status": "failed", "msg": "Insufficient funds" } }Lỗi Xác thực Dữ liệu (400)
{ "detail": { "code": 5004, "status": "failed", "msg": "Bandwidth amount out of range (400..5000)" } }Ủy quyền Thất bại / Dịch vụ Không khả dụng (503)
{ "detail": { "code": 5003, "status": "failed", "msg": "Bandwidth delegation failed" } }Tra cứu Mã Lỗi
| Mã | Mô tả | Trạng thái HTTP |
|---|---|---|
10000 | Thành công (đã ủy quyền, hoặc đã gửi TRX) | 200 |
10000 | Thành công (phản hồi từ bộ nhớ đệm) | 208 |
10001 | Đã chấp nhận, đang xử lý bởi nhà cung cấp bên ngoài | 202 |
10002 | Người nhận đã có đủ Bandwidth (không tính phí) | 200 |
10003 | Chạy thử — xem trước kết quả + giá cả, không tính phí (test=true) | 200 |
10004 | Bandwidth đã được thu hồi (chủ động hủy ủy quyền) — reclaimHash được trả về | 200 |
- | Yêu cầu trùng lặp vẫn đang được xử lý | 409 |
-1 | Khóa API không hợp lệ / IP không nằm trong danh sách trắng | 401 |
1004 | Số dư không đủ | 403 |
1005 | Không có địa chỉ thanh toán cho người dùng | 400 |
5004 | Số lượng/thời hạn không hợp lệ (xác thực dữ liệu) | 400 |
5005 | Không có gì để thu hồi (đơn hàng không ở trạng thái được ủy quyền) | 400 |
5007 | Không có kiểm định — chỉ được thuê một đơn tại một thời điểm; đơn hàng trước vẫn đang hoạt động (chờ cho đến khi kết thúc) | 503 |
5008 | Không có kiểm định — chỉ cho phép các đơn hàng 400 đơn vị; cần kiểm định đối với số lượng lớn hơn | 503 |
5003 | Ủy quyền Bandwidth thất bại / không khả dụng | 503 |
5000 | Lỗi máy chủ nội bộ | 500 |
Giới hạn Tần suất
| Khoảng thời gian | Giới hạn | Mô tả |
|---|---|---|
| 1 giây | 50 yêu cầu | Tối đa 50 yêu cầu mỗi giây trên mỗi IP |
Vượt quá Giới hạn Tần suất (429)
{ "message": "API rate limit exceeded" }Tính Bất biến
Gửi tiêu đề tùy chọn X-Idempotency-Key để việc lặp lại vô tình không tạo ra đơn hàng thứ hai — phản hồi ban đầu sẽ được trả về với HTTP 208. Nếu bạn không gửi tiêu đề này, máy chủ sẽ tự động tạo một khóa từ các tham số yêu cầu của bạn trong một khoảng thời gian ngắn.
Cách tạo khóa
Khóa có định dạng base64( HMAC-SHA256( secret, message ) ) — một chuỗi base64 gồm 44 ký tự, trong đó:
- secret = khóa API của bạn (
X-API-KEY); - message = các trường được nối với nhau bằng dấu
:—receiveAddress:amount:period:nonce.
nonce là bất kỳ giá trị nào giữ nguyên giữa các lần thử lại của cùng một đơn hàng hợp lý nhưng khác nhau giữa các đơn hàng riêng biệt — ví dụ: UUID bạn lưu giữ cho đơn hàng đó hoặc một nhóm mốc thời gian gần đúng. Tạo khóa một lần cho mỗi đơn hàng và gửi lại chính xác cùng một giá trị đó trong mỗi lần thử lại.
import hmac, hashlib, base64, time
def make_idempotency_key(api_key, receive_address, amount, period, nonce=None):
if nonce is None:
nonce = str(int(time.time() // 2)) # 2-second bucket; or your own order UUID
message = f"{receive_address}:{amount}:{period}:{nonce}"
digest = hmac.new(api_key.encode(), message.encode(), hashlib.sha256).digest()
return base64.b64encode(digest).decode() # 44-char base64# then send it as a header:
-H "X-Idempotency-Key: <base64_key>"Việc bao gồm period trong thông điệp là rất quan trọng: thuê cho cùng một địa chỉ trong 5m và trong 1h là các đơn hàng khác nhau và phải tạo ra các khóa khác nhau.
Xác thực. Giá trị
X-Idempotency-Keyđược cung cấp phải là một chuỗi base64 từ 16–64 ký tự (tập ký tựA–Z a–z 0–9 + / = _ -). Khóa sai định dạng hoặc quá dài sẽ bị từ chối với HTTP 400 (code 5004).
| Mã Trạng thái | Ý nghĩa |
|---|---|
| 200 | Đã xử lý thành công (yêu cầu đầu tiên) |
| 208 | Đã được xử lý thành công trước đó — phản hồi lưu trong bộ nhớ đệm được trả về (không tính phí lần hai) |
| 409 | Yêu cầu tương tự hiện đang được xử lý — hãy đợi, chưa thử lại lúc này |
Thử lại sau khi thất bại. Chỉ các kết quả thành công (
completed/enough) mới được lưu vào bộ nhớ đệm. Nếu lần thử trước thất bại hoặc hết thời gian chờ (chưa bị trừ tiền), bạn có thể thử lại một cách an toàn với cùng mộtX-Idempotency-Key— đơn hàng sẽ được thử lại thay vì trả về lỗi cũ. Trong khi một lượt thử vẫn đang được tiến hành, bạn sẽ nhận được mã409; hãy đợi và thử lại sau.
Lưu ý
- Các hạng mức truy cập: tài khoản được kiểm định có thể thuê bất kỳ số lượng nào trong giới hạn pool/tối đa với các đơn hàng đồng thời; không có kiểm định — 400 đơn vị một lần (đơn hàng tiếp theo chỉ sau khi lượt thuê trước kết thúc). Liên hệ với bộ phận hỗ trợ của Netts để được kiểm định.
- Tối thiểu: 400 đơn vị. Tối đa: 5000 đơn vị cho mỗi đơn hàng (cấu hình hiện tại).
- Thời hạn:
5m(300 giây) và1h(3600 giây). Bandwidth sẽ được tự động thu hồi khi hết thời hạn. - Không có phần bù dự phòng: ủy quyền chính xác số lượng được yêu cầu.
- hash là một mảng: một đơn hàng duy nhất có thể tạo ra tối đa 10 mã băm ủy quyền — tất cả đều được trả về.
- Định giá: tính phí bằng TRX, dựa trên số lượng và thời hạn yêu cầu; mức giá có thể thay đổi tùy theo thời điểm trong ngày. Liên hệ bộ phận hỗ trợ để biết giá hiện tại.
- Bù trừ đơn hàng nhỏ (ủy quyền): đối với các đơn hàng dưới 1000 đơn vị, một khoản cố định 0.372 TRX được cộng thêm vào giá như một khoản bù đắp cho chi phí ủy quyền và thu hồi trên chuỗi. Các đơn hàng từ 1000 đơn vị trở lên không có khoản cộng thêm này.
- Bù trừ gửi TRX: khi đơn hàng được thực hiện bằng cách gửi TRX (
fulfilledBy = trx), một khoản cố định 0.268 TRX sẽ được cộng thêm thay thế (bù đắp cho chi phí chuyển TRX trên chuỗi). - trx_send: chỉ áp dụng cho
amount = 400; nếu không có sẵn Bandwidth, TRX sẽ được gửi đến địa chỉ để giao dịch vẫn diễn ra thành công. - check: bỏ qua việc ủy quyền (và tính phí) khi người nhận đã có nhiều hơn 400 Bandwidth.
- Định dạng ID đơn hàng:
B5M…(5 phút) /B1H…(1 giờ). - Thời gian chờ phản hồi: tối đa khoảng ~12 giây trong khi chờ ủy quyền; thông thường là 1–2 giây.