POST /apiv2/bandwidth
Alquile Bandwidth de TRON y deléguelo a una dirección de destinatario durante un período fijo (5 minutos o 1 hora).
⚠️ Niveles de acceso.
- Las cuentas acreditadas alquilan cualquier cantidad (hasta 5000) dentro del tamaño del pool y de los límites máximos, con múltiples órdenes simultáneas. La acreditación es otorgada por el soporte de Netts.
- Sin acreditación puede alquilar 400 unidades una sola vez — la siguiente orden solo se permite después de que finalice el alquiler anterior. Las solicitudes de cantidades distintas de 400, o una segunda orden mientras la primera todavía esté activa, son rechazadas.
URL del Endpoint
POST https://netts.io/apiv2/bandwidthEncabezados de Solicitud
| Encabezado | Requerido | Descripción |
|---|---|---|
| Content-Type | Sí | application/json |
| X-API-KEY | Sí | Su clave API del panel de control de Netts |
| X-Real-IP | Sí | Dirección IP de su lista blanca |
| X-Idempotency-Key | No | Clave opcional generada por el cliente (base64) para reintentar de forma segura sin duplicar órdenes. Si se omite, el servidor genera una automáticamente |
Cuerpo de la Solicitud
{
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m"
}Parámetros
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| amount | integer | Sí | Unidades de Bandwidth a alquilar (mínimo: 400, máximo: 5000) |
| receiveAddress | string | Sí | Dirección TRON que recibirá el Bandwidth (T…, 34 caracteres, base58) |
| period | string | Sí | Duración del alquiler: "5m" (5 minutos) o "1h" (1 hora) |
| trx_send | boolean | No | Transacción garantizada: si no hay Bandwidth disponible, se envía TRX a la dirección en su lugar para que la transacción se procese igualmente. Solo funciona cuando amount = 400 (se ignora en caso contrario). Valor predeterminado false |
| check | boolean | No | Si es true y el destinatario ya tiene más de 400 de Bandwidth, la orden no se delega y no se cobran fondos (estado enough). Valor predeterminado false |
| test | boolean | No | Simulación (Dry run). Si es true, se simula el flujo completo de la orden — la respuesta le informa del resultado que ocurriría y el precio que se cobraría — sin ninguna acción en la cadena y sin cobrar. Valor predeterminado false |
Ejemplos de Solicitudes
Los ejemplos siguientes también construyen y envían el
X-Idempotency-Keypara que una repetición accidental no cree una segunda orden. Consulte Idempotencia para ver las reglas completas.
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)}")Se proporciona un ejemplo de cliente completo (Python + cURL) con el paquete del servicio (handler_bandwidth/doc/client_example/).
Respuesta
Éxito — Bandwidth delegado (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"
}
}
}Éxito — TRX enviado en lugar de Bandwidth (200 OK, solo amount=400 + trx_send=true)
Cuando el pool no tiene Bandwidth y trx_send está habilitado, se envía TRX a la dirección para que la transacción se procese igualmente. En este caso se aplica un cargo fijo, independientemente del período solicitado.
{
"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"
}
}
}Ya suficiente — no se cobra (200 OK, solo con check=true)
{
"detail": {
"code": 10002,
"status": "enough",
"msg": "enough band for 1 transfer",
"data": { "orderId": "B5M<key14>", "paidTRX": 0, "bandwidth": 400, "period": "5m" }
}
}En procesamiento — proveedor externo (202 Accepted)
Se devuelve cuando la orden se transfiere a un proveedor externo de forma asíncrona. Realice consultas periódicas (poll) al endpoint de estado (a continuación) utilizando orderId hasta que se complete.
{
"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" }
}
}Ejecución de prueba (200 OK, solo con test=true)
Se simula todo el flujo de la orden. testAction le indica lo que sucedería y wouldCostTRX lo que se cobraría. No se delega nada, no se envía TRX, no se cobra nada (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
}
}
}Valores de testAction: would_delegate (el Bandwidth se delegaría), would_trx_send (sin Bandwidth, amount=400 + trx_send → se enviaría TRX), enough (el destinatario ya tiene suficiente, con check=true), o would_error:<reason> (por ej., no_bandwidth, not_whitelisted).
Campos de Respuesta
| Campo | Tipo | Descripción |
|---|---|---|
| detail.code | integer | 10000 delegado/TRX, 10002 suficiente, 10001 en procesamiento |
| detail.status | string | completed / enough / processing / failed |
| detail.data.orderId | string | ID de la orden, formato B5M… (5m) / B1H… (1h) — utilícelo para el endpoint de estado |
| detail.data.paidTRX | number | Monto cobrado en TRX (0 cuando es enough) |
| detail.data.fulfilledBy | string | bandwidth (delegado) / trx (TRX enviado) |
| detail.data.hash | array | Hashes de transacciones de delegación (hasta 10). Siempre es un array (vacío para la rama TRX) |
| detail.data.trxSendHash | array | Hash(es) de transferencia de TRX, presente solo cuando fulfilledBy = trx |
| detail.data.bandwidth | integer | Unidades de Bandwidth delegadas |
| detail.data.period | string | Período de alquiler (5m / 1h) |
Endpoint de Estado
GET https://netts.io/apiv2/bandwidth/status/{orderId}Encabezados: X-API-KEY + X-Real-IP (la orden debe pertenecer al usuario autenticado).
| Estado de la orden | HTTP | code | status |
|---|---|---|---|
| Completada | 200 | 10000 | completed (con hash / trxSendHash) |
| En curso | 200 | 10001 | processing |
| Ya suficiente | 200 | 10002 | enough |
| Fallida | 200 | 5003 | failed |
| No encontrada / no le pertenece | 404 | -1 | — |
Endpoint de Reclamación
Reclame voluntariamente (desdelegue) el Bandwidth de una de sus órdenes delegadas antes de que su período expire. El Bandwidth se desdelega automáticamente y se devuelve el hash de la transacción.
POST https://netts.io/apiv2/bandwidth/reclaim/{orderId}Encabezados: X-API-KEY + X-Real-IP (la orden debe pertenecer al usuario autenticado).
| Estado de la orden | HTTP | code | status | Resultado |
|---|---|---|---|---|
| Delegada → reclamada ahora | 200 | 10004 | reclaimed | reclaimHash (hashes de transacciones de desdelegación) |
| Ya reclamada | 200 | 10004 | reclaimed | reclaimHash + mensaje "already reclaimed" |
| No está en estado delegado (nada que reclamar) | 400 | 5005 | failed | — |
| La reclamación aún no se ha completado | 503 | 5003 | failed | reintente en breve |
| No encontrada / no le pertenece | 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)}")El cargo por alquiler no se reembolsa en una reclamación anticipada voluntaria — reclamar solo devuelve el Bandwidth delegado al pool antes del final del período.
Respuestas de Error
Error de Autenticación (401)
{ "detail": { "code": -1, "msg": "Invalid API key or IP not in whitelist" } }Saldo Insuficiente (403)
{ "detail": { "code": 1004, "status": "failed", "msg": "Insufficient funds" } }Error de Validación (400)
{ "detail": { "code": 5004, "status": "failed", "msg": "Bandwidth amount out of range (400..5000)" } }Error de Delegación / Servicio No Disponible (503)
{ "detail": { "code": 5003, "status": "failed", "msg": "Bandwidth delegation failed" } }Referencia de Códigos de Error
| Código | Descripción | Estado HTTP |
|---|---|---|
10000 | Éxito (delegado, o TRX enviado) | 200 |
10000 | Éxito (respuesta en caché) | 208 |
10001 | Aceptada, en procesamiento por proveedor externo | 202 |
10002 | El destinatario ya tiene suficiente Bandwidth (no cobrado) | 200 |
10003 | Ejecución de prueba — vista previa del resultado + precio, no se cobra nada (test=true) | 200 |
10004 | Bandwidth reclamado (desdelegación voluntaria) — se devuelve reclaimHash | 200 |
- | Solicitud duplicada aún en procesamiento | 409 |
-1 | Clave API inválida / IP no está en la lista blanca | 401 |
1004 | Saldo insuficiente | 403 |
1005 | No hay dirección pagadora para el usuario | 400 |
5004 | Cantidad/período inválido (validación) | 400 |
5005 | Nada que reclamar (la orden no está en un estado delegado) | 400 |
5007 | Sin acreditación — solo un alquiler a la vez; la orden anterior sigue activa (espere a que finalice) | 503 |
5008 | Sin acreditación — solo se permiten órdenes de 400 unidades; se requiere acreditación para cantidades mayores | 503 |
5003 | Error en la delegación de Bandwidth / no disponible | 503 |
5000 | Error interno del servidor | 500 |
Límites de Tasa (Rate Limits)
| Período | Límite | Descripción |
|---|---|---|
| 1 segundo | 50 solicitudes | Máximo 50 solicitudes por segundo por IP |
Límite de Tasa Excedido (429)
{ "message": "API rate limit exceeded" }Idempotencia
Envíe el encabezado opcional X-Idempotency-Key para que una repetición accidental no cree una segunda orden — se devuelve la respuesta original con HTTP 208. Si no envía el encabezado, el servidor deduce una clave automáticamente a partir de los parámetros de su solicitud dentro de un breve intervalo de tiempo.
Cómo formar la clave
La clave es base64( HMAC-SHA256( secret, message ) ) — una cadena en base64 de 44 caracteres, donde:
- secret = su clave API (
X-API-KEY); - message = los campos unidos con
:—receiveAddress:amount:period:nonce.
nonce es cualquier valor que sea estable a través de los reintentos de la misma orden lógica pero diferente entre órdenes distintas — por ej. un UUID que conserve para esa orden, o un bloque de marca temporal amplio. Genere la clave una vez por orden y reenvíe exactamente el mismo valor en cada reintento.
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>"Incluir period en el mensaje es importante: alquilar para la misma dirección por 5m y por 1h son órdenes diferentes y deben producir claves diferentes.
Validación. El encabezado
X-Idempotency-Keysuministrado debe ser una cadena base64 de 16–64 caracteres (conjunto de caracteresA–Z a–z 0–9 + / = _ -). Una clave mal formada o demasiado larga es rechazada con HTTP 400 (code 5004).
| Código de Estado | Significado |
|---|---|
| 200 | Procesada exitosamente (primera solicitud) |
| 208 | Ya procesada exitosamente — se devuelve la respuesta en caché (sin segundo cobro) |
| 409 | La misma solicitud se está procesando actualmente — espere, no reintente todavía |
Reintentar después de un fallo. Solo los resultados exitosos (
completed/enough) se almacenan en caché. Si el intento anterior falló o agotó el tiempo de espera (no se cobraron fondos), puede reintentar de forma segura con el mismoX-Idempotency-Key— la orden se intentará de nuevo en lugar de devolver el error anterior. Mientras un intento siga en curso recibirá409; espere y reintente.
Notas
- Niveles de acceso: las cuentas acreditadas alquilan cualquier cantidad dentro de los límites del pool/máximos con órdenes simultáneas; sin acreditación — 400 unidades una sola vez (la siguiente orden solo después de que finalice el alquiler anterior). Póngase en contacto con el soporte de Netts para obtener la acreditación.
- Mínimo: 400 unidades. Máximo: 5000 unidades por orden (configuración actual).
- Períodos:
5m(300 s) y1h(3600 s). El Bandwidth se reclama automáticamente cuando expira el período. - Sin búfer: se delega exactamente la cantidad solicitada.
- hash es un array: una sola orden puede producir hasta 10 hashes de delegación — se devuelven todos.
- Precios: se cobra en TRX, según la cantidad y el período solicitados; las tarifas pueden variar según la hora del día. Póngase en contacto con soporte para conocer los precios actuales.
- Compensación por orden pequeña (delegación): para órdenes de menos de 1000 unidades, se añade un cargo fijo de 0.372 TRX al precio como compensación por la delegación y reclamación en la cadena. Las órdenes de 1000 unidades o más no tienen este recargo.
- Compensación por envío de TRX: cuando la orden se cumple enviando TRX (
fulfilledBy = trx), se añade en su lugar un cargo fijo de 0.268 TRX (compensación por la transferencia de TRX en la cadena). - trx_send: solo para
amount = 400; si no hay Bandwidth disponible, se envía TRX a la dirección para que la transacción se procese igualmente. - check: omite la delegación (y el cobro) cuando el destinatario ya tiene más de 400 de Bandwidth.
- Formato del ID de orden:
B5M…(5 minutos) /B1H…(1 hora). - Tiempo de espera de respuesta (timeout): hasta ~12 segundos mientras se espera la delegación; típicamente 1–2 segundos.