Orchestrator — pedidos por lotes en una sola llamada
Envía hasta 100 direcciones en una única solicitud y deja que Netts realice la secuencia completa para cada una: activar la dirección si es necesario, recargar su Bandwidth si es insuficiente, y luego alquilar la Energy — dividiendo grandes cantidades en fragmentos automáticamente.
Obtienes un 202 Accepted inmediato con una clave de seguimiento y nunca tienes que esperar en la conexión. Luego, el progreso se consulta desde el endpoint de estado.
Por qué usarlo
Pedir Energy para una dirección nueva normalmente requiere tres llamadas independientes, en el orden correcto, con tu propia lógica de reintentos entre ellas. El orquestador sintetiza eso en una sola solicitud y ejecuta la secuencia por dirección:
probe → activation (if the address is not active) → bandwidth (if free < 400) → energyUn fallo en la activación o en el Bandwidth no detiene el pedido de Energy para esa dirección, y el fallo de una dirección nunca afecta a las demás.
URL base del endpoint
https://netts.io/apiv2/orchestratorEncabezados de la solicitud
| Encabezado | Obligatorio | Descripción |
|---|---|---|
| Content-Type | Sí | application/json |
| X-API-KEY | Sí | Tu clave de API del panel de control de Netts |
| X-Real-IP | Sí | Dirección IP de tu lista blanca |
| X-Idempotency-Key | Sí* | Tu clave para este pedido, de 12 a 128 caracteres de A-Z a-z 0-9 . _ : - |
* Se requiere el encabezado X-Idempotency-Key o el campo clientRequestId en el cuerpo. Si no envías ninguno, la solicitud se rechaza con 5010.
La clave identifica el pedido completo. Repetir una solicitud con la misma clave devuelve el resultado original en lugar de crear un segundo pedido — consulta Idempotencia.
Crear un pedido — POST /apiv2/orchestrator
Cuerpo de la solicitud
{
"clientRequestId": "my-batch-2026-01-01-001",
"defaults": {
"bandwidth": true,
"bandwidthAmount": 400,
"bandwidthPeriod": "1h",
"check": true,
"trx_send": false
},
"items": [
{ "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", "amount": 65000 },
{ "receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "amount": 131000 },
{ "receiveAddress": "TYYyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy", "amount": 61000, "bandwidth": false }
]
}Campos de nivel superior
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
items | array | Sí | De 1 a 100 direcciones. Los duplicados dentro de un mismo pedido son rechazados. |
clientRequestId | string | No | Tu referencia de pedido, de 8 a 128 caracteres de A-Z a-z 0-9 . _ : -. Funciona también como clave de idempotencia si el encabezado está ausente. |
defaults | object | No | Valores aplicados a cada elemento que no los anule explícitamente. |
Campos de cada elemento
Todos los campos excepto receiveAddress y amount también pueden definirse en defaults. Un valor en el elemento tiene prioridad sobre el valor por defecto.
| Campo | Tipo | Por defecto | Descripción |
|---|---|---|---|
receiveAddress | string | — | Dirección TRON que recibe la Energy |
amount | int | — | Energy para esta dirección, 61 000 … 50 000 000 |
bandwidth | bool | true | Pedir Bandwidth para esta dirección cuando sea insuficiente |
bandwidthAmount | int | 400 | 400 o 5000 |
bandwidthPeriod | string | 1h | 5m o 1h |
check | bool | ver abajo | Comprobar primero el Bandwidth libre y omitir el pedido si hay suficiente |
trx_send | bool | false | Se transmite directamente al servicio de Bandwidth |
activation | bool | true | Activar la dirección si no está activa. Establece false para omitir el paso para una dirección que ya sabes que está activa. |
check tiene el valor por defecto de true cuando bandwidthAmount es 400, y false en caso contrario — pedir 5 000 unidades normalmente significa que las deseas independientemente de lo que ya esté disponible.
Las cantidades son por dirección. Una solicitud puede combinar diferentes cantidades libremente; el único límite es el total.
Límites
| Límite | Valor |
|---|---|
| Direcciones por pedido | 100 |
| Energy por dirección | 61 000 … 50 000 000 |
| Energy total por pedido | 50 000 000 |
| Pedidos en curso por cuenta | 3 |
| Direcciones en curso por cuenta | 300 |
| Saldo mínimo para ser aceptado | 4 TRX |
El límite de 50 000 000 se aplica a la suma de todas las direcciones en la solicitud, no a cada una de ellas.
Respuesta — aceptada (202, código 10202)
{
"detail": {
"code": 10202,
"status": "accepted",
"msg": "Order accepted for processing",
"data": {
"idempotencyKey": "my-batch-2026-01-01-001",
"requestId": 1234,
"itemsAccepted": 3,
"statusUrl": "/apiv2/orchestrator/status/my-batch-2026-01-01-001",
"items": [
{
"deliveryKey": 5001,
"trackingId": "my-batch-2026-01-01-001:TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"amount": 65000,
"energyChunks": 1,
"activation": "planned",
"bandwidth": "planned",
"status": "queued"
}
]
}
}
}202 significa en cola, no ejecutado. Aún no se ha cobrado nada. Haz sondeos en statusUrl para obtener el resultado.
trackingId es el par clave de idempotencia + dirección — la identidad de una dirección dentro de tu pedido. Utilízalo en tus propios registros y conciliaciones.
Ejemplo
curl -X POST https://netts.io/apiv2/orchestrator \
-H "Content-Type: application/json" \
-H "X-API-KEY: your_api_key" \
-H "X-Real-IP: your_whitelisted_ip" \
-H "X-Idempotency-Key: my-batch-2026-01-01-001" \
-d '{
"items": [
{"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", "amount": 65000}
]
}'Consultar progreso — GET /apiv2/orchestrator/status/{idempotencyKey}
Añade ?address=T… para obtener una única dirección en lugar del pedido completo.
{
"detail": {
"code": 10000,
"status": "processing",
"data": {
"idempotencyKey": "my-batch-2026-01-01-001",
"requestId": 1234,
"clientRequestId": "my-batch-2026-01-01-001",
"summary": {
"total": 3, "queued": 1, "processing": 1, "completed": 1,
"partial": 0, "failed": 0, "insufficient_balance": 0,
"credentials_revoked": 0, "cancelled": 0
},
"items": [
{
"deliveryKey": 5001,
"trackingId": "my-batch-2026-01-01-001:TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
"status": "completed",
"energy": {
"requested": 65000,
"delegated": 65000,
"status": "done",
"chunks": { "total": 1, "done": 1 },
"orderIds": ["1Hxxxxxxxxxx"],
"hashes": ["0000000000000000000000000000000000000000000000000000000000000000"]
},
"activation": { "status": "not_needed", "orderId": null, "hash": null },
"bandwidth": {
"status": "enough", "orderId": "B1Hxxxxxxxxxxxxxx",
"amount": 400, "period": "1h", "hashes": [], "skipReason": null
},
"attempts": 1,
"startedAt": "2026-01-01T00:00:00+00:00",
"finishedAt": "2026-01-01T00:00:03+00:00"
}
]
}
}
}Una clave desconocida, o una que pertenezca a otra cuenta, devuelve 404.
Valores de estado de la dirección
| Estado | Significado |
|---|---|
queued | Esperando ser procesada |
processing | En curso |
completed | Toda la Energy solicitada ha sido delegada |
partial | Algunos fragmentos entregados, algunos fallidos |
failed | Nada entregado |
insufficient_balance | Detenido — tu saldo cayó por debajo del mínimo |
credentials_revoked | Tu clave de API fue eliminada o deshabilitada mientras el pedido se ejecutaba |
cancelled | Eliminado de la cola mediante tu solicitud de cancelación |
Valores de estado de los pasos
| Paso | Valores |
|---|---|
activation | not_needed, done, failed, skipped, skipped_unavailable |
bandwidth | enough, done, failed, skipped |
energy | done, partial, failed |
bandwidth.skipReason explica el motivo de skipped: option_off (lo deshabilitaste), energy_gt_600000 (los pedidos grandes de Energy no necesitan una recarga de Bandwidth).
Hashes de delegación
energy.hashes es tu comprobante de entrega. Cuando la Energy proviene de un proveedor externo, el hash no se conoce al momento de realizar el pedido — se completa aproximadamente un minuto después, y la dirección no se reporta como finalizada hasta que se recopilan los hashes o expira la ventana de espera. Una dirección en completed con un hash presente está totalmente liquidada.
Cancelar — POST /apiv2/orchestrator/cancel/{idempotencyKey}
Elimina de la cola cada dirección que aún no haya sido tomada.
{
"detail": {
"code": 10005,
"status": "cancelled",
"msg": "Order cancelled: 7 addresses removed from queue",
"data": { "cancelled": 7 }
}
}Las direcciones que ya están en processing no se interrumpen: parte de su Energy ya podría estar pagada. La cancelación se realiza según el principio del mejor esfuerzo en el resto.
Idempotencia
El pedido se identifica mediante tu clave — el encabezado X-Idempotency-Key, o clientRequestId cuando el encabezado está ausente.
| Solicitud repetida | Resultado |
|---|---|
| Misma clave, mismo cuerpo | 208 con el pedido original y originalAcceptedAt — ningún segundo pedido |
| Misma clave, cuerpo diferente | 409 4090 IDEMPOTENCY_CONFLICT |
Por lo tanto, en caso de un tiempo de espera de red de tu lado, es seguro reintentar de forma idéntica. Modificar la carga útil bajo una clave ya utilizada es rechazado en lugar de aplicarse silenciosamente.
Dentro del pedido, cada dirección lleva su propia clave interna, por lo que una repetición nunca cobra dos veces a una misma dirección tampoco.
Facturación
El orquestador en sí no cobra nada. Cada paso es facturado por el servicio que lo realiza, a su precio normal:
| Paso | Cobrado como |
|---|---|
| Activación | deducción independiente, número de pedido A… |
| Bandwidth | deducción independiente, número de pedido B1H… — solo cuando realmente se delega |
| Energy | una deducción por fragmento, número de pedido 1H… |
check: true con suficiente Bandwidth libre no cuesta nada — el estado es enough y no se realiza ningún pedido. Las cantidades grandes de Energy omiten el Bandwidth por completo.
Si tu saldo se agota en mitad del lote, las direcciones restantes terminan como insufficient_balance sin llegar a intentarse.
Referencia de códigos de error
| Código | Descripción | Estado HTTP |
|---|---|---|
10202 | Pedido aceptado / ya aceptado | 202 / 208 |
10000 | Estado devuelto | 200 |
10005 | Pedido cancelado | 200 |
5004 | Campo inválido: formato de dirección, amount fuera de rango, bandwidthAmount distinto de 400/5000, bandwidthPeriod distinto de 5m/1h, cuerpo no es un objeto JSON | 400 |
5005 | items faltante o vacío | 400 |
5006 | receiveAddress duplicada en un mismo pedido | 400 |
5009 | X-Idempotency-Key o clientRequestId con formato incorrecto | 400 |
5010 | No se proporcionó ni X-Idempotency-Key ni clientRequestId | 400 |
5012 | La Energy total en la solicitud supera los 50 000 000 | 400 |
-1 | Clave de API inválida / IP no incluida en la lista blanca | 401 |
1004 | Saldo por debajo del mínimo de 4 TRX | 402 |
-1 | Pedido no encontrado (o no te pertenece) | 404 |
4090 | IDEMPOTENCY_CONFLICT — misma clave, cuerpo diferente | 409 |
4220 | Error de validación de la solicitud (detalles en data.errors) | 422 |
429 / 5011 | Demasiados pedidos, direcciones o fragmentos en curso | 429 |
5003 | El pedido no fue aceptado — servicio temporalmente no disponible, es seguro reintentar | 503 |
Un 503 en la creación es seguro ante fallos: no se almacenó nada y no se cobró nada.
Límites de velocidad
Limitado por IP de origen:
| Período | Límite |
|---|---|
| 1 segundo | 20 solicitudes |
Límite de velocidad excedido (429)
{ "message": "API rate limit exceeded" }Notas
- 202 no es un comprobante de entrega. Considéralo como "en cola". El resultado se encuentra en el endpoint de estado.
- Las direcciones se ejecutan en paralelo, hasta 5 a la vez dentro de un mismo pedido, por lo que un lote grande no espera por una sola dirección lenta. El orden de finalización no está garantizado.
- La fragmentación es automática: las cantidades superiores a 1 000 000 se dividen en fragmentos uniformes, convirtiéndose cada uno en su propio pedido de Energy.
energy.orderIdsyenergy.hasheslos enumeran todos. - No hay webhooks para pedidos del orquestador en su conjunto. Cada delegación de Energy sigue generando el habitual webhook
delegation.confirmed, consulta Webhooks. - Endpoints relacionados: Activator, Bandwidth, Order 1H.