Skip to content

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) → energy

A 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/orchestrator

Request Headers

HeaderRequiredDescription
Content-TypeYesapplication/json
X-API-KEYYesYour API key from the Netts dashboard
X-Real-IPYesIP address from your whitelist
X-Idempotency-KeyYes*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

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

FieldTypeRequiredDescription
itemsarrayYes1 to 100 addresses. Duplicates within one order are rejected.
clientRequestIdstringNoYour order reference, 8–128 chars of A-Z a-z 0-9 . _ : -. Doubles as the idempotency key if the header is absent.
defaultsobjectNoValues 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.

FieldTypeDefaultDescription
receiveAddressstringTRON address receiving the energy
amountintEnergy for this address, 61 000 … 50 000 000
bandwidthbooltrueOrder bandwidth for this address when it is short
bandwidthAmountint400400 or 5000
bandwidthPeriodstring1h5m or 1h
checkboolsee belowCheck free bandwidth first and skip the order if there is enough
trx_sendboolfalsePassed through to the bandwidth service
activationbooltrueActivate 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

LimitValue
Addresses per order100
Energy per address61 000 … 50 000 000
Total energy per order50 000 000
Orders in flight per account3
Addresses in flight per account300
Minimum balance to be accepted4 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)

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

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

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

StatusMeaning
queuedWaiting to be picked up
processingIn progress
completedAll requested energy delegated
partialSome chunks delivered, some failed
failedNothing delivered
insufficient_balanceStopped — your balance fell below the minimum
credentials_revokedYour API key was removed or disabled while the order was running
cancelledRemoved from the queue by your cancel request

Step status values

StepValues
activationnot_needed, done, failed, skipped, skipped_unavailable
bandwidthenough, done, failed, skipped
energydone, 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.

json
{
    "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 requestResult
Same key, same body208 with the original order and originalAcceptedAt — no second order
Same key, different body409 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:

StepCharged as
Activationseparate deduction, order number A…
Bandwidthseparate deduction, order number B1H… — only when actually delegated
Energyone 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

CodeDescriptionHTTP Status
10202Order accepted / already accepted202 / 208
10000Status returned200
10005Order cancelled200
5004Invalid field: address format, amount out of range, bandwidthAmount not 400/5000, bandwidthPeriod not 5m/1h, body not a JSON object400
5005items missing or empty400
5006Duplicate receiveAddress in one order400
5009Malformed X-Idempotency-Key or clientRequestId400
5010Neither X-Idempotency-Key nor clientRequestId provided400
5012Total energy in the request exceeds 50 000 000400
-1Invalid API key / IP not in whitelist401
1004Balance below the 4 TRX minimum402
-1Order not found (or not yours)404
4090IDEMPOTENCY_CONFLICT — same key, different body409
4220Request validation failed (details in data.errors)422
429 / 5011Too many orders, addresses or chunks in flight429
5003Order was not accepted — service temporarily unavailable, safe to retry503

A 503 on create is fail-secure: nothing was stored and nothing was charged.

Rate Limits

Limited per source IP:

PeriodLimit
1 second20 requests

Rate Limit Exceeded (429)

json
{ "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.orderIds and energy.hashes list them all.
  • No webhook for orchestrator orders as a whole. Each energy delegation still produces the usual delegation.confirmed webhook, see Webhooks.
  • Related endpoints: Activator, Bandwidth, Order 1H.