Orchestrator — пакетные заказы в одном вызове
Отправляйте до 100 адресов в одном запросе, и Netts выполнит всю цепочку действий для каждого из них: активирует адрес при необходимости, пополнит его Bandwidth при нехватке, затем арендует Energy — автоматически разделяя большие объёмы на части.
Вы мгновенно получаете ответ 202 Accepted с ключом отслеживания и не держите соединение открытым. Ход выполнения затем считывается через эндпоинт статуса.
Зачем использовать
Заказ Energy для нового адреса обычно требует трёх отдельных вызовов в строгом порядке с собственной логикой повторов между ними. Orchestrator объединяет всё это в один запрос и выполняет последовательность для каждого адреса:
probe → activation (if the address is not active) → bandwidth (if free < 400) → energyСбой на этапе активации или Bandwidth не останавливает заказ Energy для этого адреса, а ошибка по одному адресу никогда не влияет на остальные.
Базовый URL эндпоинта
https://netts.io/apiv2/orchestratorЗаголовки запроса
| Заголовок | Обязательный | Описание |
|---|---|---|
| Content-Type | Да | application/json |
| X-API-KEY | Да | Ваш API-ключ из панели управления Netts |
| X-Real-IP | Да | IP-адрес из вашего белого списка |
| X-Idempotency-Key | Да* | Ваш ключ для этого заказа, от 12 до 128 символов A-Z a-z 0-9 . _ : - |
* Требуется либо заголовок X-Idempotency-Key, либо поле clientRequestId в теле запроса. Если не указано ни то, ни другое, запрос отклоняется с кодом 5010.
Ключ идентифицирует весь заказ целиком. Повторный запрос с тем же ключом возвращает первоначальный результат вместо создания второго заказа — см. Идемпотентность.
Создание заказа — POST /apiv2/orchestrator
Тело запроса
{
"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 }
]
}Поля верхнего уровня
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
items | array | Да | От 1 до 100 адресов. Дубликаты внутри одного заказа отклоняются. |
clientRequestId | string | Нет | Ваш идентификатор заказа, от 8 до 128 символов A-Z a-z 0-9 . _ : -. Служит ключом идемпотентности, если заголовок отсутствует. |
defaults | object | Нет | Значения, применяемые к каждому элементу, где они не переопределены явно. |
Поля элементов
Любое поле, кроме receiveAddress и amount, также может быть задано в defaults. Значение на уровне элемента имеет приоритет над значением по умолчанию.
| Поле | Тип | По умолчанию | Описание |
|---|---|---|---|
receiveAddress | string | — | Адрес TRON, получающий Energy |
amount | int | — | Объём Energy для этого адреса, 61 000 … 50 000 000 |
bandwidth | bool | true | Заказывать Bandwidth для этого адреса при его нехватке |
bandwidthAmount | int | 400 | 400 или 5000 |
bandwidthPeriod | string | 1h | 5m или 1h |
check | bool | см. ниже | Сначала проверить свободный Bandwidth и пропустить заказ, если его достаточно |
trx_send | bool | false | Передаётся напрямую в сервис Bandwidth |
activation | bool | true | Активировать адрес, если он не активен. Укажите false, чтобы пропустить этот шаг для адреса, о котором точно известно, что он уже активен. |
Поле check по умолчанию имеет значение true, если bandwidthAmount равен 400, и false в остальных случаях — заказ 5 000 единиц обычно означает, что они требуются независимо от текущего остатка.
Объёмы указываются для каждого адреса. В одном запросе можно свободно комбинировать различные значения; единственное ограничение — общая сумма.
Лимиты
| Лимит | Значение |
|---|---|
| Адресов в заказе | 100 |
| Energy на один адрес | 61 000 … 50 000 000 |
| Всего Energy на заказ | 50 000 000 |
| Активных заказов в обработке на аккаунт | 3 |
| Адресов в обработке на аккаунт | 300 |
| Минимальный баланс для приёма заказа | 4 TRX |
Ограничение в 50 000 000 применяется к сумме по всем адресам в запросе, а не к каждому по отдельности.
Ответ — принято (202, код 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 означает помещено в очередь, но не выполнено. Средства ещё не списаны. Опрашивайте statusUrl для получения результата.
Значение trackingId представляет собой пару ключ идемпотентности + адрес — это идентификатор одного адреса внутри вашего заказа. Используйте его в собственных логах и для сверки данных.
Пример
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}
]
}'Проверка статуса — GET /apiv2/orchestrator/status/{idempotencyKey}
Добавьте ?address=T…, чтобы получить данные по одному адресу вместо всего заказа.
{
"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"
}
]
}
}
}Неизвестный ключ или ключ, принадлежащий другому аккаунту, возвращает 404.
Значения статуса адреса
| Статус | Описание |
|---|---|
queued | В очереди на обработку |
processing | Выполняется |
completed | Вся запрошенная Energy делегирована |
partial | Часть объёма доставлена, часть завершилась ошибкой |
failed | Ничего не доставлено |
insufficient_balance | Остановлено — ваш баланс опустился ниже минимума |
credentials_revoked | Ваш API-ключ был удалён или отключён во время выполнения заказа |
cancelled | Удалено из очереди по вашему запросу на отмену |
Значения статуса шагов
| Шаг | Значения |
|---|---|
activation | not_needed, done, failed, skipped, skipped_unavailable |
bandwidth | enough, done, failed, skipped |
energy | done, partial, failed |
Поле bandwidth.skipReason поясняет значение skipped: option_off (вы отключили опцию), energy_gt_600000 (крупные заказы Energy не требуют пополнения Bandwidth).
Хеши делегирования
Поле energy.hashes является вашим подтверждением доставки. Когда Energy поступает от внешнего провайдера, хеш неизвестен в момент заказа — он появляется примерно через минуту, и адрес не отмечается как завершённый до тех пор, пока хеши не будут собраны или пока не истечёт окно ожидания. Адрес со статусом completed и заполненным хешем считается полностью рассчитанным.
Отмена заказа — POST /apiv2/orchestrator/cancel/{idempotencyKey}
Удаляет из очереди все адреса, обработка которых ещё не началась.
{
"detail": {
"code": 10005,
"status": "cancelled",
"msg": "Order cancelled: 7 addresses removed from queue",
"data": { "cancelled": 7 }
}
}Адреса, уже находящиеся в статусе processing, не прерываются: часть Energy для них уже может быть оплачена. Отмена выполняется по принципу максимальных усилий (best-effort) для оставшихся адресов.
Идемпотентность
Заказ идентифицируется вашим ключом — заголовком X-Idempotency-Key или полем clientRequestId, если заголовок отсутствует.
| Повторный запрос | Результат |
|---|---|
| Тот же ключ, то же тело | 208 с данными исходного заказа и полем originalAcceptedAt — повторный заказ не создаётся |
| Тот же ключ, другое тело | 409 4090 IDEMPOTENCY_CONFLICT |
Таким образом, при тайм-ауте сети на вашей стороне можно безопасно повторить отправку исходного запроса. Изменение полезной нагрузки под уже использованным ключом отклоняется, а не применяется молча.
Внутри заказа каждый адрес снабжён собственным внутренним ключом, поэтому повторный запрос также исключает двойное списание за один и тот же адрес.
Оплата
Сам сервис Orchestrator не взимает комиссию. Каждый шаг тарифицируется выполнившим его сервисом по его обычной стоимости:
| Шаг | Формат списания |
|---|---|
| Активация | отдельное списание, номер заказа A… |
| Bandwidth | отдельное списание, номер заказа B1H… — только при фактическом делегировании |
| Energy | одно списание за каждый фрагмент, номер заказа 1H… |
При параметре check: true и достаточном свободном количестве Bandwidth плата не взимается — статус принимает значение enough, а заказ не создаётся. При крупных объёмах Energy шаг заказа Bandwidth полностью пропускается.
Если баланс исчерпается в процессе обработки пакета, оставшиеся адреса получат статус insufficient_balance без попытки исполнения.
Справочник кодов ошибок
| Код | Описание | HTTP-статус |
|---|---|---|
10202 | Заказ принят / уже был принят ранее | 202 / 208 |
10000 | Статус успешно возвращён | 200 |
10005 | Заказ отменён | 200 |
5004 | Недопустимое поле: формат адреса, amount вне диапазона, bandwidthAmount не равен 400/5000, bandwidthPeriod не равен 5m/1h, тело запроса не является объектом JSON | 400 |
5005 | Поле items отсутствует или пусто | 400 |
5006 | Дублирующийся receiveAddress внутри одного заказа | 400 |
5009 | Некорректный формат X-Idempotency-Key или clientRequestId | 400 |
5010 | Не передан ни X-Idempotency-Key, ни clientRequestId | 400 |
5012 | Общий объём Energy в запросе превышает 50 000 000 | 400 |
-1 | Неверный API-ключ / IP-адрес отсутствует в белом списке | 401 |
1004 | Баланс ниже минимума в 4 TRX | 402 |
-1 | Заказ не найден (или принадлежит другому аккаунту) | 404 |
4090 | IDEMPOTENCY_CONFLICT — тот же ключ, но другое тело запроса | 409 |
4220 | Ошибка валидации запроса (подробности в data.errors) | 422 |
429 / 5011 | Слишком много заказов, адресов или частей заказа в обработке | 429 |
5003 | Заказ не был принят — сервис временно недоступен, можно безопасно повторить попытку | 503 |
Ошибка 503 при создании заказа безопасна к сбоям (fail-secure): никакие данные не сохраняются и средства не списываются.
Ограничения частоты запросов (Rate Limits)
Ограничения действуют на исходящий IP-адрес:
| Период | Лимит |
|---|---|
| 1 секунда | 20 запросов |
Превышение лимита запросов (429)
{ "message": "API rate limit exceeded" }Примечания
- Код 202 не является подтверждением доставки. Рассматривайте его как статус «помещено в очередь». Итоговый результат отдаётся через эндпоинт статуса.
- Адреса обрабатываются параллельно, до 5 одновременно внутри одного заказа, поэтому большой пакет не простаивает из-за одного медленного адреса. Порядок завершения обработки не гарантируется.
- Дробление выполняется автоматически: объёмы свыше 1 000 000 делятся на равные части, каждая из которых превращается в отдельный заказ Energy. Поля
energy.orderIdsиenergy.hashesсодержат их полный список. - Вебхук на весь заказ Orchestrator целиком не предусмотрен. Каждое отдельное делегирование Energy генерирует стандартный вебхук
delegation.confirmed, см. Вебхуки. - Связанные эндпоинты: Activator, Bandwidth, Order 1H.