Skip to content
Translated page. The English version is the source of truth.

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/bandwidth

Encabezados de solicitud ​

HeaderRequiredDescription
Content-TypeYesapplication/json
X-API-KEYYesSu clave de API del panel de Netts
X-Real-IPYesDirección IP de su lista blanca
X-Idempotency-KeyNoClave 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 ​

json
{
    "amount": 1500,
    "receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "period": "5m"
}

Parámetros de solicitud ​

ParameterTypeRequiredDescription
amountintegerYesUnidades de Bandwidth a alquilar (mínimo: 400, máximo: 5000)
receiveAddressstringYesDirección TRON que recibirá el Bandwidth (T…, 34 caracteres, base58)
periodstringYesDuración del alquiler: "5m" (5 minutos) o "1h" (1 hora, solo cuentas acreditadas)
trx_sendbooleanNoTransacció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
checkbooleanNoSi 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
testbooleanNoSimulació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-Key para que una repetición accidental no cree una segunda orden. Consulte Idempotency para ver las reglas completas.

cURL ​

bash
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 ​

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) ​

json
{
    "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.

json
{
    "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) ​

json
{
    "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.

json
{
    "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).

json
{
    "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 ​

FieldTypeDescription
detail.codeinteger10000 delegado/TRX, 10002 suficiente, 10001 procesando
detail.statusstringcompleted / enough / processing / failed
detail.data.orderIdstringID de la orden, formato B5M… (5m) / B1H… (1h) — utilícelo para el endpoint de estado
detail.data.paidTRXnumberMonto cobrado en TRX (0 cuando es enough)
detail.data.fulfilledBystringbandwidth (delegado) / trx (TRX enviado)
detail.data.hasharrayHashes de transacciones de delegación (hasta 10). Siempre es un arreglo (vacío para la rama TRX)
detail.data.trxSendHasharrayHash(es) de transferencia TRX, presente solo cuando fulfilledBy = trx
detail.data.bandwidthintegerUnidades de Bandwidth delegadas
detail.data.periodstringPerí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 ordenHTTPcodestatus
Completada20010000completed (con hash / trxSendHash)
En progreso20010001processing
Ya suficiente20010002enough
Fallida2005003failed
No encontrada / no le pertenece404-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 ordenHTTPcodestatusResultado
Delegada → recuperada ahora20010004reclaimedreclaimHash (hashes de la transacción de retiro de delegación)
Ya recuperada20010004reclaimedreclaimHash + mensaje "already reclaimed"
No está en estado delegado (nada que recuperar)4005005failed—
La recuperación aún no se completó5035003failedreintentar en breve
No encontrada / no le pertenece404-1——
bash
curl -X POST https://netts.io/apiv2/bandwidth/reclaim/B5M<...> \
  -H "X-API-KEY: your_api_key" -H "X-Real-IP: your_whitelisted_ip"
json
{
    "detail": {
        "code": 10004,
        "status": "reclaimed",
        "msg": "Bandwidth reclaimed",
        "data": { "orderId": "B5M<...>", "reclaimHash": ["<txid>"] }
    }
}
python
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) ​

json
{ "detail": { "code": -1, "msg": "Invalid API key or IP not in whitelist" } }

Saldo insuficiente (403) ​

json
{ "detail": { "code": 1004, "status": "failed", "msg": "Insufficient funds" } }

Error de validación (400) ​

json
{ "detail": { "code": 5004, "status": "failed", "msg": "Bandwidth amount out of range (400..5000)" } }

Delegación fallida / Servicio no disponible (503) ​

json
{ "detail": { "code": 5003, "status": "failed", "msg": "Bandwidth delegation failed" } }

Referencia de códigos de error ​

CodeDescriptionHTTP Status
10000Éxito (delegado, o TRX enviado)200
10000Éxito (respuesta en caché)208
10001Aceptado, en procesamiento por proveedor externo202
10002El destinatario ya tiene suficiente Bandwidth (no se cobra)200
10003Ejecución de prueba — vista previa de resultado + precio, no se cobra nada (test=true)200
10004Bandwidth recuperado (retiro voluntario de delegación) — reclaimHash devuelto200
-Solicitud duplicada aún en procesamiento409
-1Clave de API no válida / IP no incluida en la lista blanca401
1004Saldo insuficiente403
1005Sin dirección pagadora para el usuario400
5004Cantidad/período no válidos (validación)400
5005Nada que recuperar (la orden no está en un estado delegado)400
5007Sin acreditación — solo un alquiler a la vez; la orden anterior sigue activa (espere a que finalice)503
5008Sin acreditación — solo se permiten órdenes de 400 unidades por 5 minutos; se requiere acreditación para cantidades mayores o 1 hora503
5003Fallo en la delegación de Bandwidth / no disponible503
5000Error interno del servidor500

Límites de tasa ​

PeriodLimitDescription
1 segundo50 solicitudesMáximo de 50 solicitudes por segundo por IP

Límite de tasa excedido (429) ​

json
{ "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.

python
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
bash
# 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-Key provisto debe ser una cadena base64 de 16–64 caracteres (conjunto de caracteres A–Z a–z 0–9 + / = _ -). Una clave mal formada o demasiado larga se rechaza con HTTP 400 (code 5004).

Código de estadoSignificado
200Procesado exitosamente (primera solicitud)
208Ya procesado exitosamente — se devuelve la respuesta en caché (sin segundo cobro)
409La 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 mismo X-Idempotency-Key — se vuelve a intentar procesar la orden en lugar de devolver el error anterior. Mientras un intento sigue en curso obtiene 409; 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 con enough (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) ​

json
{
    "amount": 1000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "period": "5m",
    "test": true
}
json
{
    "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 ​

json
{
    "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"
        }
    }
}
FieldDescription
paidTRXCosto del servicio en TRX. Para cuentas de pospago no se deduce del depósito
paymentModepostpaid
totalTRXMonto 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) ​

json
{
    "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 ​

CodeHTTPDescription
1004402Límite de crédito de pospago alcanzado
5032503Precio no disponible temporalmente
5034503Facturación no disponible temporalmente — la orden no fue aceptada
5036503Verificació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) y 1h (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.