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

POST /apiv2/order1h ​

Создать заказ на аренду энергии на 1 час через нескольких поставщиков энергии с автоматическим переключением при сбоях.

URL эндпоинта ​

POST https://netts.io/apiv2/order1h

Заголовки запроса ​

ЗаголовокОбязательныйОписание
Content-TypeДаapplication/json
X-API-KEYДаВаш API-ключ из панели управления Netts
X-Real-IPДаIP-адрес из вашего белого списка

Тело запроса ​

json
{
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}

Параметры запроса ​

ПараметрТипОбязательныйОписание
amountintegerДаКоличество арендуемой энергии (минимум: 61000, максимум: 3000000)
receiveAddressstringДаАдрес TRON, который получит энергию (формат TRC-20)

Выбор поставщика ​

API автоматически выбирает оптимального поставщика энергии на основе:

  • Экономической эффективности — всегда находит самую низкую доступную цену
  • Доступности — гарантирует достаточные резервы энергии
  • Надежности — использует поставщиков с высоким показателем успешности
  • Скорости — отдает приоритет наиболее быстрому времени доставки

Примеры ​

cURL ​

bash
curl -X POST https://netts.io/apiv2/order1h \
  -H "Content-Type: application/json" \
  -H "X-API-KEY: your_api_key" \
  -H "X-Real-IP: your_whitelisted_ip" \
  -d '{
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
  }'

Python ​

python
import requests

url = "https://netts.io/apiv2/order1h"
headers = {
    "Content-Type": "application/json",
    "X-API-KEY": "your_api_key",
    "X-Real-IP": "your_whitelisted_ip"
}

payload = {
    "amount": 131000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE"
}

response = requests.post(url, headers=headers, json=payload)
data = response.json()

if response.status_code == 200:
    detail = data.get('detail', {})
    order_data = detail.get('data', {})
    print(f"Order ID: {order_data.get('orderId')}")
    print(f"Transaction Hash: {order_data.get('hash')}")
    print(f"Energy Delivered: {order_data.get('energy')}")
    print(f"Cost: {order_data.get('paidTRX')} TRX")
    print(f"Delegate Address: {order_data.get('delegateAddress')}")
else:
    error_detail = data.get('detail', data)
    print(f"Error Code: {error_detail.get('code', 'N/A')}")
    print(f"Error Message: {error_detail.get('msg', error_detail)}")

Ответ ​

Успешный ответ (200 OK) ​

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 2.23 TRX deducted",
        "data": {
            "orderId": "1H123456",
            "paidTRX": 2.23,
            "hash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
            "delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq",
            "energy": 131050
        }
    }
}

Поля ответа ​

ПолеТипОписание
detail.codeintegerВсегда 10000 для успешных заказов
detail.msgstringСообщение об успехе с указанием списанной суммы
detail.data.orderIdstringУнифицированный идентификатор заказа (формат: 1H{request_id})
detail.data.paidTRXnumberОбщая стоимость в TRX (включает комиссию за активацию, если адрес не был активирован)
detail.data.hashstring | nullХеш транзакции. Поле присутствует всегда, но может быть пустым — некоторые поставщики не возвращают хеш мгновенно. Используйте /apiv2/order_check через 1 минуту, чтобы получить хеш
detail.data.delegateAddressstringАдрес пула, который делегировал энергию
detail.data.energyintegerКоличество энергии + буфер (обычно +50)

Ответы с ошибкой ​

Ошибка аутентификации (401) ​

json
{
    "detail": "Invalid API key or IP not in whitelist"
}

Недостаточный баланс (403) ​

json
{
    "code": 1004,
    "msg": "Insufficient funds. Required: 2.23 TRX, Available: 1.50 TRX"
}

Сервис недоступен (503) ​

json
{
    "code": 5003,
    "msg": "Service temporarily unavailable. All energy providers are currently unavailable."
}

Ошибки поставщика (503) ​

json
{
    "code": 5001,
    "msg": "Energy provider temporarily unavailable"
}
json
{
    "code": 5002,
    "msg": "Energy provider temporarily unavailable"
}
json
{
    "code": 5004,
    "msg": "Energy provider requires higher minimum amount"
}

Внутренняя ошибка сервера (500) ​

json
{
    "code": 5000,
    "msg": "Internal server error occurred"
}

Справочник кодов ошибок ​

КодОписаниеHTTP-статус
10000Успешно200
10000Успешно (кэшированный ответ)208
-Повторный запрос все еще обрабатывается409
1004Недостаточный баланс403
5000Внутренняя ошибка сервера500
5001Поставщик энергии недоступен503
5002Поставщик энергии недоступен503
5003Сервис энергии недоступен503
5004Не соблюден минимум поставщика энергии503

Ограничения частоты запросов ​

К данному эндпоинту применяются следующие ограничения частоты запросов (на один IP-адрес):

ПериодЛимитОписание
1 секунда50 запросовМаксимум 50 запросов в секунду

Заголовки ограничений частоты запросов ​

http
RateLimit-Limit: 50
RateLimit-Remaining: 49
RateLimit-Reset: 1
X-RateLimit-Limit-Second: 50
X-RateLimit-Remaining-Second: 49

Превышение лимита запросов (429) ​

json
{
    "message": "API rate limit exceeded"
}

Идемпотентность ​

API поддерживает идемпотентность для предотвращения повторной обработки заказов. Когда вы отправляете несколько идентичных запросов, система гарантирует, что заказ будет обработан только один раз.

Как работает идемпотентность ​

Уникальность запроса определяется комбинацией следующих параметров:

  • Временная метка запроса (окно в 1 секунду)
  • Количество энергии
  • Адрес получателя
  • API-ключ

Каждому запросу предоставляется 1-секундное окно уникальности. Для защиты системы от злоупотреблений и обеспечения корректной обработки запросы с идентичными параметрами не могут отправляться чаще одного раза в секунду.

Текущее поведение: Система автоматически защищает клиентов от ошибочных повторов для уже заказанной энергии. Если вы случайно отправите один и тот же запрос дважды, средства не будут списаны повторно.

Передача собственного ключа ​

Вы можете взять управление идемпотентностью в свои руки, передавая заголовок X-Idempotency-Key. При его наличии только это значение определяет, является ли запрос повторным, а автоматическая комбинация выше не используется. Когда он отсутствует, ничего не меняется — сервер формирует ключ за вас.

ЗаголовокX-Idempotency-Key
ФорматРовно 64 шестнадцатеричных символа в нижнем регистре — дайджест SHA-256
Время жизни24 часа с момента первого запроса, содержащего этот ключ
Область действияВаш аккаунт. Одинаковое значение, отправленное другим аккаунтом, никогда не вернет ваш результат

Ключ любого другого формата — UUID с дефисами, base64, шестнадцатеричные символы в верхнем регистре — отклоняется с кодом 400 до размещения заказа и до списания каких-либо средств:

json
{
    "detail": "Invalid idempotency key format. Must be 64-character hexadecimal string."
}

Формат отличается от других эндпоинтов. /apiv2/withdraw, /apiv2/bandwidth и оркестратор принимают ключ base64 длиной от 16 до 64 символов. Этот эндпоинт принимает только 64-символьный шестнадцатеричный дайджест, поэтому код генерации ключа, скопированный из тех эндпоинтов, вернет здесь 400.

Как формировать ключ ​

Формируйте его на основе вашего API-ключа. Это сделает значение уникальным для вашего аккаунта, воспроизводимым при повторной попытке и недоступным для подбора кем-либо еще:

python
import hashlib
import hmac

def make_idempotency_key(api_key: str, address: str, amount: int, nonce: str) -> str:
    message = f"{address}:{amount}:{nonce}"
    return hmac.new(api_key.encode(), message.encode(), hashlib.sha256).hexdigest()

Значение nonce относится к заказу, а не к запросу. Выберите его один раз, когда заказ создается на вашей стороне, и передавайте это же значение при каждой отправке данного заказа — как при первой попытке, так и при каждом повторе. Генерация нового значения внутри функции отправки (str(uuid.uuid4()) при каждом вызове) дает каждой попытке свой ключ, поэтому повтор после таймаута будет принят как второй заказ и оплачен повторно. Самый простой и надежный выбор — идентификатор заказа, который у вас уже есть: он существует до первой попытки и сохраняется при перезапуске вашего процесса.

python
# один раз, когда заказ появляется в вашей системе
order = create_order(address="TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE", amount=131000)

# при первой попытке и при каждом повторе — те же три параметра, тот же ключ
key = make_idempotency_key(API_KEY, order.address, order.amount, order.id)

headers = {
    "Content-Type": "application/json",
    "X-API-KEY": API_KEY,
    "X-Idempotency-Key": key,
}

Ключ живет 24 часа. После этого тот же nonce снова свободен и инициирует новый заказ.

Не используйте значения, к которым может прийти кто-то другой — 64 нуля, дайджест фиксированного слова. Пространство ключей разделяется между аккаунтами. Такая коллизия никогда не раскроет заказ другого аккаунта, но ваш запрос будет отклоняться с кодом 409, пока не истечет срок действия их ключа, что совсем не тот ответ, который вы хотите получить посреди повторной попытки.

Размещение двух идентичных заказов ​

Иногда вам действительно необходимо создать два одинаковых заказа — то же количество энергии на тот же адрес, один за другим. Автоматический ключ не может отличить такую ситуацию от повтора: два запроса идентичны байт в байт, и единственное, что их разделяет, — это момент их поступления.

Без собственного ключа результат зависит от промежутка времени между ними:

Промежуток между двумя запросамиЧто происходит
В пределах одного 1-секундного окнаВторой запрос принимается за повтор. Он не выполняется: вы получаете 208 и ответ первого заказа, включая orderId. Средства за него не списываются
С разницей более секундыДва разных ключа — оба заказа размещаются и оба оплачиваются

Поэтому, если вы полагаетесь на автоматический ключ, выдерживайте паузу более одной секунды между двумя одинаковыми заказами и проверяйте статус-код: 208 означает, что заказ, который вы только что отправили, не был размещен.

Пауза — это временное решение, а не исправление. Она разделяет каждый запрос, включая те, которые вы вовсе не планировали повторять: повтор после таймаута, двойной клик, повторная доставка сообщения из вашей очереди. Они также приходят позже указанного окна, поэтому размещаются как отдельные заказы и списываются отдельно. Таймаут ответа этого эндпоинта составляет 10 секунд, что уже далеко за пределами окна: автоматический ключ не защищает повтор, следующий после таймаута.

Собственный ключ избавляет от неопределенности, поскольку принятие решения переносится на единственную сторону, знающую правильный ответ:

Что вы делаетеЧто вы отправляетеРезультат
Второй, действительно новый заказНовый nonceНовый ключ — заказ размещен
Повтор заказа, результат которого вам неизвестенЗначение nonce первой попыткиТот же ключ — 208, исходный ответ, никакого второго списания

Вторая строка — это именно та причина, по которой существует заголовок, и именно здесь в реализациях чаще всего возникают ошибки: см. примечание в разделе Как формировать ключ.

HTTP-статусы для повторяющихся запросов ​

Код состоянияНазваниеОписание
200OKЗаказ успешно обработан (первый запрос)
208Already ReportedЗаказ уже был обработан, возвращается кэшированный ответ
409ConflictЗапрос в данный момент обрабатывается, не повторяйте попытку

Повторный запрос — уже обработан (208) ​

При получении повторного запроса для уже выполненного заказа:

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 2.54 TRX deducted",
        "data": {
            "hash": "9e4c20e21e01e4c39b21b670d1ea1fc1e4b0de94d8fbd4c190d5378ba911dfae",
            "energy": 65050,
            "orderId": "1H70bcc7962a",
            "paidTRX": 2.535,
            "delegateAddress": "TNp5gsJhBmZFXgCdgjMgr8pEZ8fHgXUHDq"
        }
    },
    "idempotency": {
        "status": "completed",
        "cached": true,
        "original_created_at": "2025-12-03T10:34:49.104896"
    }
}

Тело ответа идентично исходному успешному ответу, с добавлением объекта idempotency, указывающего, что это кэшированный ответ.

Повторный запрос — еще обрабатывается (409) ​

Если повторный запрос поступает в то время, когда исходный еще обрабатывается:

json
{
    "success": false,
    "error": "duplicate_request_processing",
    "message": "This request is currently being processed. Please wait and do not retry.",
    "idempotency_key": "b9e67b2412d33c92a4f0e1c3d5b7a9f2e4c6d8b0a2f4e6c8d0b2a4f6e8c0d2b4",
    "retry_after_seconds": 3
}

Рекомендация: Подождите указанное количество секунд retry_after_seconds перед проверкой статуса заказа.

Рекомендации ​

  • Не отправляйте параллельные запросы с одинаковыми параметрами — дождитесь ответа на каждый
  • Используйте новый nonce для каждого нового заказа, и nonce первой попытки для каждого ее повтора
  • Никогда не генерируйте nonce заново в момент отправки — повторная попытка должна воспроизводить ключ первой попытки, а не создавать новый
  • Обрабатывайте ответы 409 ожиданием, а не немедленным повтором
  • Проверяйте поле idempotency.cached для определения кэшированных ответов — статус 208 означает, что отправленный вами заказ не был размещен

Постоплатные аккаунты ​

Аккаунты с постоплатной системой расчетов используют тот же эндпоинт, URL, заголовки и тело запроса, что и все остальные. Разница заключается в способе оплаты заказа:

  • С вашего депозита ничего не списывается. Каждый успешный заказ добавляется к сумме задолженности вашего аккаунта в валюте расчетов, зафиксированной в вашем договоре. Вы оплачиваете ее по счету в соответствии с вашими договоренностями.
  • У вашего аккаунта есть кредитный лимит. Пока сумма задолженности находится в пределах лимита, заказы принимаются даже при нулевом депозите.
  • Оплачиваются только фактически оказанные услуги. Отклоненный или невыполненный заказ ничего не стоит.
  • Если адрес получателя требует активации, активация входит в состав того же заказа и выставляется отдельной строкой.

Постоплатная система расчетов подключается со стороны Netts по запросу для конкретного аккаунта. Каждый ответ сообщает, как именно оплачивается заказ: параметр paymentMode имеет значение postpaid или prepaid.

Дополнительные поля запроса ​

ПараметрТипОбязательныйОписание
testbooleanНетtrue — только рассчитать стоимость. Ничего не заказывается, не доставляется и не списывается
freezePricebooleanНетtrue — зафиксировать цену по вашему договору на 60 секунд. Ничего не заказывается и не списывается
quoteIdstringНетРазместить заказ по стоимости котировки, выданной через freezePrice
priceCurrencystringНетTRX (по умолчанию) или валюта вашего договора, как в settlement.asset. Для постоплатных аккаунтов суммы в валюте договора включаются всегда

Параметр quoteId нельзя комбинировать с test или freezePrice. Любое другое дополнительное поле в теле запроса отклоняется.

Проверка цены (test: true) ​

json
{
    "amount": 65000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "test": true
}
json
{
    "detail": {
        "code": 10010,
        "msg": "Test calculation",
        "data": {
            "amount": 65000,
            "unitPriceSun": "20",
            "discount": null,
            "energyTRX": "1.300000",
            "activationTRX": "1.100000",
            "wouldCostTRX": "2.400000",
            "paidTRX": 0,
            "paymentMode": "postpaid",
            "activationCheck": "inactive",
            "alt": {"USDC": {"energy": "0.430541", "activation": "0.364304", "total": "0.794845"}},
            "fxAt": "2026-10-19T07:15:18.469870+00:00"
        }
    }
}
ПолеОписание
unitPriceSunЦена за единицу энергии в SUN с учетом вашей персональной скидки, если она предусмотрена
discountВаша персональная скидка (type, value) или null
energyTRX / activationTRX / wouldCostTRXЭнергия, активация (если адресу она требуется) и общая сумма в TRX
activationCheckinactive — адрес будет активирован и включен в счет; active — активация не требуется; unknown — не удалось проверить в данный момент
alt.<currency>Те же суммы в валюте вашего договора
fxAtВремя фиксации обменного курса, использованного для сумм в валюте договора

Фиксированная котировка (freezePrice: true) ​

Используйте котировку, чтобы зафиксировать стоимость по вашему договору до создания заказа.

  1. Отправьте заказ с параметром "freezePrice": true. Ответ будет содержать код 10011 (Quote issued), те же поля, что и при проверке цены, а также quoteId и expiresAt.
  2. В течение 60 секунд отправьте заказ с параметром "quoteId": "<quoteId>" и теми же самыми amount и receiveAddress.
  3. Заказ рассчитывается по зафиксированной в котировке цене — стоимости по вашему договору на момент выдачи котировки — даже если тариф за это время изменился.

Котировку можно использовать один раз и только для того же продукта: 1-часовая котировка не может оплатить 5-минутный заказ. Истекшая или уже использованная котировка отклоняется, и заказ не создается.

json
{
    "amount": 65000,
    "receiveAddress": "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
    "quoteId": "q_4f540f16a2c94b7f8e3d1a6b5c0e9d72"
}

Успешный заказ ​

json
{
    "detail": {
        "code": 10000,
        "msg": "Successful, 1.30 TRX for energy + 1.10 TRX for address activation, postpaid",
        "data": {
            "orderId": "1Hf9544a1508",
            "paidTRX": 2.4,
            "hash": "032bda8fa6911b42c15a6d8d30520dc22bcc4077972a1503b6a3fae491967eb4",
            "delegateAddress": "TVnkj2jHKgmea8DVJFo2teD7rRSpH51bne",
            "energy": 65000,
            "activationHash": "259e1ab276114ae717a6f62d7d25eb1f89a2dccb637cbe41be626df3c2a78519",
            "paymentMode": "postpaid",
            "energyTRX": "1.300000",
            "activationTRX": "1.100000",
            "totalTRX": "2.400000"
        }
    }
}
ПолеОписание
paidTRXСтоимость услуги в TRX. Для постоплатных аккаунтов она не списывается с депозита
paymentModepostpaid
energyTRX / activationTRX / totalTRXТочные суммы с точностью до 6 знаков после запятой
quoteId, altПрисутствуют, если заказ был размещен по котировке: идентификатор котировки и зафиксированные суммы
activationFinalПрисутствует и имеет значение false только тогда, когда сумма активации является предварительной; окончательная сумма указывается в вашем счете

Все остальные поля аналогичны предоплатным заказам.

Достигнут кредитный лимит (402) ​

json
{
    "detail": {
        "code": 1004,
        "msg": "Postpaid credit limit reached.",
        "paymentMode": "postpaid",
        "reason": "limit_reached"
    }
}

Заказ не выполняется, и средства не начисляются к оплате. Прием новых заказов возобновляется после поступления вашей оплаты или увеличения кредитного лимита.

Коды ошибок постоплаты ​

КодHTTPОписание
10010200Результат проверки цены (test)
10011200Котировка выдана (freezePrice)
1004402Достигнут кредитный лимит постоплаты
4100400Некорректный запрос
4101400Неподдерживаемая валюта priceCurrency
4102400quoteId скомбинирован с test или freezePrice
4103409Котировка уже использована
4104409Срок действия котировки истек
4105409Ключ идемпотентности уже использован для другого запроса
4106404Котировка не найдена
4107409Параметры заказа отличаются от условий котировки
4108400Неверный формат quoteId
4109422Недоступно для субаккаунтов
5032503Цена временно недоступна
5033503Обменный курс временно недоступен
5034503Биллинг временно недоступен — заказ не был принят
5036503Проверка кредитного лимита временно недоступна — повторите попытку позже

Для всех приведенных выше ответов 4xx и 503 заказ не создается и начисления не производятся.

Примечания ​

  • Энергия доставляется мгновенно после успешного оформления заказа (обычно в течение 0.5–10 секунд)
  • Таймаут ответа API: максимум 10 секунд, стандартное время ответа составляет до 2 секунд
  • Активация адреса: если адрес получателя не активирован, Netts активирует его по себестоимости
  • Задержка активации: для неактивированных адресов время ответа API может составлять до 6 секунд из-за процесса активации
  • Заказы обрабатываются круглосуточно (24/7) с автоматическим переключением между поставщиками
  • Минимальное количество энергии: 61 000 единиц
  • Максимальное количество энергии: 3 000 000 единиц на один заказ
  • Буфер энергии: +50 единиц добавляются автоматически для компенсации со стороны поставщика (бесплатно)
  • Хеш транзакции: поле присутствует всегда, но может быть пустым, если поставщик не вернул его сразу. Чтобы получить хеш, вызовите /apiv2/order_check не ранее чем через 1 минуту после создания заказа
  • Выбор поставщика: происходит автоматически на основе цены и доступности
  • Формат ID заказа: 1H{request_id} для унифицированного отслеживания
  • Ценообразование: динамическое, зависит от времени суток и объема энергии
  • Длительность: фиксированно 1 час (3600 секунд)
  • Ограничение частоты запросов: 50 запросов в секунду с одного IP-адреса