Orchestrator — batch orders in one call
Send up to 100 addresses in a single request and let Netts do the whole sequence for each one: activate the address if needed, top up its bandwidth if it is short, then rent the energy — splitting large amounts into chunks automatically.
You get an immediate 202 Accepted with a tracking key and never wait on the connection. Progress is then read from the status endpoint.
Why use it
Ordering energy for a fresh address normally takes three separate calls, in the right order, with your own retry logic between them. The orchestrator collapses that into one request and runs the sequence per address:
probe → activation (if the address is not active) → bandwidth (if free < 400) → energyA failure in activation or bandwidth does not stop the energy order for that address, and one address failing never affects the others.
Endpoint base URL
https://netts.io/apiv2/orchestratorRequest Headers
| Header | Required | Description |
|---|---|---|
| Content-Type | Yes | application/json |
| X-API-KEY | Yes | Your API key from the Netts dashboard |
| X-Real-IP | Yes | IP address from your whitelist |
| X-Idempotency-Key | Yes* | Your key for this order, 12–128 chars of A-Z a-z 0-9 . _ : - |
* Either the X-Idempotency-Key header or the clientRequestId field in the body is required. If you send neither, the request is rejected with 5010.
The key identifies the whole order. Repeating a request with the same key returns the original result instead of creating a second order — see Idempotency.
Create an order — POST /apiv2/orchestrator
Request body
{
"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 }
]
}Top-level fields
| Field | Type | Required | Description |
|---|---|---|---|
items | array | Yes | 1 to 100 addresses. Duplicates within one order are rejected. |
clientRequestId | string | No | Your order reference, 8–128 chars of A-Z a-z 0-9 . _ : -. Doubles as the idempotency key if the header is absent. |
defaults | object | No | Values applied to every item that does not override them. |
Item fields
Every field except receiveAddress and amount may also be set in defaults. A value on the item wins over the default.
| Field | Type | Default | Description |
|---|---|---|---|
receiveAddress | string | — | TRON address receiving the energy |
amount | int | — | Energy for this address, 61 000 … 50 000 000 |
bandwidth | bool | true | Order bandwidth for this address when it is short |
bandwidthAmount | int | 400 | 400 or 5000 |
bandwidthPeriod | string | 1h | 5m or 1h |
check | bool | see below | Check free bandwidth first and skip the order if there is enough |
trx_send | bool | false | Passed through to the bandwidth service |
activation | bool | true | Activate the address if it is not active. Set false to skip the step for an address you know is already active. |
check defaults to true when bandwidthAmount is 400, and to false otherwise — ordering 5 000 units usually means you want them regardless of what is already there.
Amounts are per address. One request may mix different amounts freely; the only ceiling is the total.
Limits
| Limit | Value |
|---|---|
| Addresses per order | 100 |
| Energy per address | 61 000 … 50 000 000 |
| Total energy per order | 50 000 000 |
| Orders in flight per account | 3 |
| Addresses in flight per account | 300 |
| Minimum balance to be accepted | 4 TRX |
The 50 000 000 ceiling applies to the sum over all addresses in the request, not to each one.
Response — accepted (202, code 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 means queued, not executed. Nothing has been charged yet. Poll statusUrl for the result.
trackingId is the pair idempotency key + address — the identity of one address inside your order. Use it in your own logs and reconciliation.
Example
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}
]
}'Check progress — GET /apiv2/orchestrator/status/{idempotencyKey}
Add ?address=T… to get a single address instead of the whole order.
{
"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"
}
]
}
}
}An unknown key, or one belonging to another account, returns 404.
Address status values
| Status | Meaning |
|---|---|
queued | Waiting to be picked up |
processing | In progress |
completed | All requested energy delegated |
partial | Some chunks delivered, some failed |
failed | Nothing delivered |
insufficient_balance | Stopped — your balance fell below the minimum |
credentials_revoked | Your API key was removed or disabled while the order was running |
cancelled | Removed from the queue by your cancel request |
Step status values
| Step | Values |
|---|---|
activation | not_needed, done, failed, skipped, skipped_unavailable |
bandwidth | enough, done, failed, skipped |
energy | done, partial, failed |
bandwidth.skipReason explains a skipped: option_off (you disabled it), energy_gt_600000 (large energy orders do not need a bandwidth top-up).
Delegation hashes
energy.hashes is your proof of delivery. When the energy comes from an external provider the hash is not known at order time — it is filled in about a minute later, and the address is not reported as finished until the hashes are collected or the wait window expires. An address in completed with a hash present is fully settled.
Cancel — POST /apiv2/orchestrator/cancel/{idempotencyKey}
Removes from the queue every address that has not been picked up yet.
{
"detail": {
"code": 10005,
"status": "cancelled",
"msg": "Order cancelled: 7 addresses removed from queue",
"data": { "cancelled": 7 }
}
}Addresses already in processing are not interrupted: part of their energy may already be paid for. Cancel is best-effort on the remainder.
Idempotency
The order is identified by your key — the X-Idempotency-Key header, or clientRequestId when the header is absent.
| Repeat request | Result |
|---|---|
| Same key, same body | 208 with the original order and originalAcceptedAt — no second order |
| Same key, different body | 409 4090 IDEMPOTENCY_CONFLICT |
So a network timeout on your side is safe to retry verbatim. Changing the payload under an already used key is rejected rather than silently applied.
Inside the order, each address carries its own internal key, so a repeat never double-charges a single address either.
Billing
The orchestrator itself charges nothing. Each step is billed by the service that performs it, at its normal price:
| Step | Charged as |
|---|---|
| Activation | separate deduction, order number A… |
| Bandwidth | separate deduction, order number B1H… — only when actually delegated |
| Energy | one deduction per chunk, order number 1H… |
check: true with enough free bandwidth costs nothing — the status is enough and no order is placed. Large energy amounts skip bandwidth entirely.
If your balance runs out mid-batch, the remaining addresses end as insufficient_balance without being attempted.
Error Code Reference
| Code | Description | HTTP Status |
|---|---|---|
10202 | Order accepted / already accepted | 202 / 208 |
10000 | Status returned | 200 |
10005 | Order cancelled | 200 |
5004 | Invalid field: address format, amount out of range, bandwidthAmount not 400/5000, bandwidthPeriod not 5m/1h, body not a JSON object | 400 |
5005 | items missing or empty | 400 |
5006 | Duplicate receiveAddress in one order | 400 |
5009 | Malformed X-Idempotency-Key or clientRequestId | 400 |
5010 | Neither X-Idempotency-Key nor clientRequestId provided | 400 |
5012 | Total energy in the request exceeds 50 000 000 | 400 |
-1 | Invalid API key / IP not in whitelist | 401 |
1004 | Balance below the 4 TRX minimum | 402 |
-1 | Order not found (or not yours) | 404 |
4090 | IDEMPOTENCY_CONFLICT — same key, different body | 409 |
4220 | Request validation failed (details in data.errors) | 422 |
429 / 5011 | Too many orders, addresses or chunks in flight | 429 |
5003 | Order was not accepted — service temporarily unavailable, safe to retry | 503 |
A 503 on create is fail-secure: nothing was stored and nothing was charged.
Rate Limits
Limited per source IP:
| Period | Limit |
|---|---|
| 1 second | 20 requests |
Rate Limit Exceeded (429)
{ "message": "API rate limit exceeded" }Notes
- 202 is not a delivery receipt. Treat it as "queued". The result lives in the status endpoint.
- Addresses run in parallel, up to 5 at a time within one order, so a large batch does not wait on a single slow address. Order of completion is not guaranteed.
- Chunking is automatic: amounts above 1 000 000 are split into even chunks, each becoming its own energy order.
energy.orderIdsandenergy.hasheslist them all. - No webhook for orchestrator orders as a whole. Each energy delegation still produces the usual
delegation.confirmedwebhook, see Webhooks. - Related endpoints: Activator, Bandwidth, Order 1H.