POST /apiv2/bandwidth
Alquile Bandwidth de TRON y deléguelo a una dirección de destinatario por un período fijo: 5 minutos, o 1 hora para cuentas acreditadas.
⚠️ Niveles de acceso.
- Cuentas acreditadas alquilan cualquier cantidad (hasta 5000) por 5 minutos o 1 hora dentro del tamaño del pool y 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 por 5 minutos, una sola vez — la siguiente orden se permite únicamente después de que finalice el alquiler anterior. Las solicitudes de cantidades distintas de 400, por 1 hora, o una segunda orden mientras la primera sigue activa, son rechazadas.
URL del endpoint
POST https://netts.io/apiv2/bandwidthEncabezados de solicitud
| Header | Required | Description |
|---|---|---|
| Content-Type | Yes | application/json |
| X-API-KEY | Yes | Su clave de API del panel de Netts |
| X-Real-IP | Yes | 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 de solicitud
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | integer | Yes | Unidades de Bandwidth a alquilar (mínimo: 400, máximo: 5000) |
| receiveAddress | string | Yes | Dirección TRON que recibirá el Bandwidth (T…, 34 caracteres, base58) |
| period | string | Yes | Duración del alquiler: "5m" (5 minutos) o "1h" (1 hora, solo cuentas acreditadas) |
| 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. Funciona solo cuando amount = 400 (se ignora en caso contrario). 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). Predeterminado false |
| test | boolean | No | Simulación (dry run). Si es true, se simula el flujo completo de la orden — la respuesta le informa el resultado que ocurriría y el precio que se cobraría — sin ninguna acción en la cadena y sin realizar cobros. Predeterminado false |
Ejemplos
Los siguientes ejemplos también construyen y envían el
X-Idempotency-Keypara que una repetición accidental no cree una segunda orden. Consulte Idempotency 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. Consulte periódicamente el endpoint de estado (a continuación) utilizando el 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 sería delegado), 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 ejemplo, no_bandwidth, not_whitelisted).
Campos de la respuesta
| Field | Type | Description |
|---|---|---|
| detail.code | integer | 10000 delegado/TRX, 10002 suficiente, 10001 procesando |
| 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 arreglo (vacío para la rama TRX) |
| detail.data.trxSendHash | array | Hash(es) de transferencia 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 progreso | 200 | 10001 | processing |
| Ya suficiente | 200 | 10002 | enough |
| Fallida | 200 | 5003 | failed |
| No encontrada / no le pertenece | 404 | -1 | — |
Endpoint de recuperación (Reclaim)
Recupere voluntariamente (retire la delegación de) el Bandwidth de una de sus órdenes delegadas antes de que su período expire. El Bandwidth se desvincula 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 → recuperada ahora | 200 | 10004 | reclaimed | reclaimHash (hashes de la transacción de retiro de delegación) |
| Ya recuperada | 200 | 10004 | reclaimed | reclaimHash + mensaje "already reclaimed" |
| No está en estado delegado (nada que recuperar) | 400 | 5005 | failed | — |
| La recuperación aún no se completó | 503 | 5003 | failed | reintentar 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 costo del alquiler no se reembolsa en una recuperación voluntaria anticipada — recuperar solo devuelve el Bandwidth delegado al pool antes de que finalice el 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)" } }Delegación fallida / Servicio no disponible (503)
{ "detail": { "code": 5003, "status": "failed", "msg": "Bandwidth delegation failed" } }Referencia de códigos de error
| Code | Description | HTTP Status |
|---|---|---|
10000 | Éxito (delegado, o TRX enviado) | 200 |
10000 | Éxito (respuesta en caché) | 208 |
10001 | Aceptado, en procesamiento por proveedor externo | 202 |
10002 | El destinatario ya tiene suficiente Bandwidth (no se cobra) | 200 |
10003 | Ejecución de prueba — vista previa de resultado + precio, no se cobra nada (test=true) | 200 |
10004 | Bandwidth recuperado (retiro voluntario de delegación) — reclaimHash devuelto | 200 |
- | Solicitud duplicada aún en procesamiento | 409 |
-1 | Clave de API no válida / IP no incluida en la lista blanca | 401 |
1004 | Saldo insuficiente | 403 |
1005 | Sin dirección pagadora para el usuario | 400 |
5004 | Cantidad/período no válidos (validación) | 400 |
5005 | Nada que recuperar (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 por 5 minutos; se requiere acreditación para cantidades mayores o 1 hora | 503 |
5003 | Fallo en la delegación de Bandwidth / no disponible | 503 |
5000 | Error interno del servidor | 500 |
Límites de tasa
| Period | Limit | Description |
|---|---|---|
| 1 segundo | 50 solicitudes | Máximo de 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 una breve ventana de tiempo.
Cómo formar la clave
La clave es base64( HMAC-SHA256( secret, message ) ) — una cadena base64 de 44 caracteres, donde:
- secret = su clave de API (
X-API-KEY); - message = los campos unidos con
:—receiveAddress:amount:period:nonce.
nonce es cualquier valor que sea estable en los reintentos de la misma orden lógica pero diferente entre órdenes distintas — por ejemplo, un UUID que conserve para esa orden, o un bloque de marca de tiempo aproximado. 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 distintas.
Validación. Un
X-Idempotency-Keyprovisto debe ser una cadena base64 de 16–64 caracteres (conjunto de caracteresA–Z a–z 0–9 + / = _ -). Una clave mal formada o demasiado larga se rechaza con HTTP 400 (code 5004).
| Código de estado | Significado |
|---|---|
| 200 | Procesado exitosamente (primera solicitud) |
| 208 | Ya procesado exitosamente — se devuelve la respuesta en caché (sin segundo cobro) |
| 409 | La misma solicitud se está procesando actualmente — espere, no reintente todavía |
Reintentar tras un error. Solo los resultados exitosos (
completed/enough) se almacenan en caché. Si el intento anterior falló o expiró por tiempo (no se cobraron fondos), puede reintentar de forma segura con el mismoX-Idempotency-Key— se vuelve a intentar procesar la orden en lugar de devolver el error anterior. Mientras un intento sigue en curso obtiene409; espere y reintente.
Cuentas de pospago
Las cuentas con facturación de pospago utilizan el mismo endpoint, URL, encabezados y cuerpo de solicitud que todos los demás. La diferencia radica en cómo se paga la orden:
- No se deduce nada de su depósito. Cada orden entregada se agrega al saldo pendiente de su cuenta en la moneda de liquidación acordada en su contrato. Lo paga mediante factura, de acuerdo con su acuerdo.
- Su cuenta tiene un límite de crédito. Mientras el monto adeudado esté dentro del límite, las órdenes se aceptan incluso con un depósito en cero. Los alquileres por 5 minutos y por 1 hora se contabilizan contra el mismo límite de Bandwidth.
- Solo se facturan los servicios entregados: Bandwidth delegado a la dirección, o TRX enviado en su lugar (
fulfilledBy = trx). El monto es el mismo que para las órdenes de prepago. - Una orden rechazada, no ejecutada, una ejecución de prueba (
test: true) o respondida conenough(check: true) no cuesta nada. - Una recuperación voluntaria anticipada no reduce el monto adeudado, al igual que para las órdenes de prepago.
- Los niveles de acceso, cantidades, períodos y todas las demás reglas de este endpoint son los mismos que para las cuentas de prepago.
Netts habilita la facturación de pospago para una cuenta a pedido. Cada respuesta le informa cómo se paga la orden: paymentMode es postpaid o prepaid.
Consulta de precio (test: true)
{
"amount": 1000,
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"period": "5m",
"test": true
}{
"detail": {
"code": 10003,
"status": "test",
"msg": "Test run — no on-chain action, no charge",
"data": {
"orderId": "B5M1a2b3c4d5e6f70",
"testAction": "would_delegate",
"wouldCostTRX": 0.7,
"paidTRX": 0,
"bandwidth": 1000,
"period": "5m",
"receiverFreeBandwidth": 600,
"paymentMode": "postpaid"
}
}
}wouldCostTRX es el monto que se agregaría a su saldo adeudado, en TRX. No se delega ni se factura nada.
Orden exitosa
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful, 0.700000 TRX, postpaid",
"data": {
"orderId": "B5M0f9e8d7c6b5a41",
"paidTRX": 0.7,
"fulfilledBy": "bandwidth",
"hash": ["<txid>"],
"bandwidth": 1000,
"period": "5m",
"paymentMode": "postpaid",
"totalTRX": "0.700000"
}
}
}| Field | Description |
|---|---|
| paidTRX | Costo del servicio en TRX. Para cuentas de pospago no se deduce del depósito |
| paymentMode | postpaid |
| totalTRX | Monto exacto, con 6 decimales |
Todos los demás campos, incluida la rama TRX (fulfilledBy = trx, trxSendHash), son los mismos que para las órdenes de prepago.
Límite de crédito alcanzado (402)
{
"detail": {
"code": 1004,
"msg": "Postpaid credit limit reached.",
"paymentMode": "postpaid",
"reason": "limit_reached"
}
}La orden no se ejecuta y no se factura nada. Se volverán a aceptar nuevas órdenes una vez que se registre su pago o se incremente su límite.
Códigos de error de pospago
| Code | HTTP | Description |
|---|---|---|
1004 | 402 | Límite de crédito de pospago alcanzado |
5032 | 503 | Precio no disponible temporalmente |
5034 | 503 | Facturación no disponible temporalmente — la orden no fue aceptada |
5036 | 503 | Verificación de crédito no disponible temporalmente — reintente más tarde |
Para todas las respuestas anteriores, no se ordena nada y no se factura nada. Todos los demás códigos son los mismos que para las órdenes de prepago.
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 por 5 minutos, 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, solo cuentas acreditadas). El Bandwidth se recupera automáticamente cuando expira el período. - Sin búfer: se delega exactamente la cantidad solicitada.
- hash es un arreglo: 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 el soporte para consultar los precios actuales.
- Compensación por órdenes pequeñas (delegación): para órdenes de menos de 1000 unidades, se agrega un valor fijo de 0.372 TRX al precio como compensación por la delegación y recuperació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 completa enviando TRX (
fulfilledBy = trx), se agrega en su lugar un valor 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 la orden:
B5M…(5 minutos) /B1H…(1 hora). - Tiempo de espera de respuesta: hasta ~12 segundos mientras se espera la delegación; normalmente 1–2 segundos.