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

POST /apiv2/order1h ​

Створення замовлення на оренду Energy на 1 годину через кількох постачальників Energy з автоматичним перемиканням у разі збоїв (failover).

URL кінцевої точки ​

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

Заголовки запиту ​

HeaderRequiredDescription
Content-TypeТакapplication/json
X-API-KEYТакВаш API-ключ із панелі керування Netts
X-Real-IPТакIP-адреса з вашого білого списку

Тіло запиту ​

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

Параметри ​

ParameterTypeRequiredDescription
amountintegerТакКількість Energy для оренди (мінімум: 61000, максимум: 3000000)
receiveAddressstringТакАдреса TRON, яка отримає Energy (формат TRC-20)

Вибір постачальника ​

API автоматично обирає оптимального постачальника Energy на основі:

  • Цінової ефективності — завжди знаходить найнижчу доступну ціну
  • Доступності — гарантує достатні резерви Energy
  • Надійності — використовує постачальників із високим показником успішності
  • Швидкості — надає пріоритет найшвидшому часу доставки

Приклади ​

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
        }
    }
}

Поля відповіді ​

FieldTypeDescription
detail.codeintegerЗавжди 10000 для успішних замовлень
detail.msgstringПовідомлення про успіх зі списаною сумою
detail.data.orderIdstringУніфікований ID замовлення (формат: 1H{request_id})
detail.data.paidTRXnumberЗагальна вартість у TRX (включає комісію за активацію, якщо адреса не була активована)
detail.data.hashstring | nullХеш транзакції. Поле завжди присутнє, але може бути порожнім — деякі постачальники не повертають хеш одразу. Використовуйте /apiv2/order_check через 1 хвилину, щоб отримати хеш
detail.data.delegateAddressstringАдреса пулу, яка делегувала Energy
detail.data.energyintegerКількість Energy + буфер (зазвичай +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"
}

Довідник кодів помилок ​

CodeDescriptionHTTP Status
10000Успіх200
10000Успіх (кешована відповідь)208
-Дублікат запиту ще обробляється409
1004Недостатній баланс403
5000Внутрішня помилка сервера500
5001Постачальник Energy недоступний503
5002Постачальник Energy недоступний503
5003Сервіс Energy недоступний503
5004Не досягнуто мінімуму постачальника Energy503

Ліміти запитів ​

До цього ендпоінту застосовуються такі обмеження частоти запитів (на одну IP-адресу):

PeriodLimitDescription
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-секундне вікно)
  • Кількість Energy
  • Адреса отримувача
  • API-ключ

Кожному запиту надається 1-секундне вікно унікальності. Щоб захистити систему від зловживань і забезпечити коректну обробку, запити з ідентичними параметрами не можна надсилати частіше ніж раз на секунду.

Поточна поведінка: Система автоматично захищає клієнтів від помилкових повторних спроб для вже замовленої Energy. Якщо ви випадково надішлете один і той самий запит двічі, з вас не буде списано кошти повторно.

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

Ви можете взяти контроль над ідемпотентністю у свої руки, передаючи заголовок X-Idempotency-Key. Якщо він присутній, саме це значення одноосібно визначає, чи є запит повторним, а автоматична комбінація, зазначена вище, не використовується. Якщо він відсутній, нічого не змінюється — сервер генерує ключ автоматично.

HeaderX-Idempotency-Key
FormatРівно 64 шістнадцяткових символи в нижньому регістрі — хеш SHA-256
Lifetime24 години з моменту першого запиту з цим ключем
ScopeВаш акаунт. Те саме значення, надіслане з іншого акаунта, ніколи не поверне ваш результат

Ключ будь-якого іншого формату — UUID з дефісами, base64, hex у верхньому регістрі — відхиляється з кодом 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, доки не мине термін дії їхнього ключа, що є небажаною відповіддю під час повторної спроби.

Розміщення двох ідентичних замовлень ​

Іноді вам дійсно потрібно розмістити однакове замовлення двічі — ту саму кількість Energy на ту саму адресу, одне за одним. Автоматичний ключ не здатний відрізнити це від повторної спроби: обидва запити байт-у-байт ідентичні, і єдине, що їх відрізняє, — це момент їхнього надходження.

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

Інтервал між двома запитамиЩо відбувається
У межах того самого 1-секундного вікнаДругий запит вважається повтором. Він не виконується: ви отримуєте 208 і відповідь першого замовлення включно з orderId. Кошти за нього не списуються
З різницею понад одну секундуДва різні ключі — обидва замовлення розміщуються і за обидва списуються кошти

Тому, якщо ви покладаєтеся на автоматичний ключ, робіть паузу понад одну секунду між двома однаковими замовленнями та аналізуйте код статусу: 208 означає, що щойно надіслане замовлення не було розміщено.

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

Власний ключ позбавляє від здогадок, оскільки прийняття рішення переноситься на єдину сторону, якій відома відповідь:

Що ви робитеЩо ви надсилаєтеРезультат
Друге, дійсно нове замовленняНовий nonceНовий ключ — замовлення розміщується
Повтор замовлення, результат якого вам невідомийnonce першої спробиТой самий ключ — 208, початкова відповідь, без повторного списання

Другий рядок — це причина існування заголовка, і саме тут у реалізаціях найчастіше виникають помилки: див. примітку в розділі Як сформувати ключ.

Коди стану HTTP для повторних запитів ​

Status CodeNameDescription
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.

Додаткові поля запиту ​

ParameterTypeRequiredDescription
testbooleanНіtrue — лише розрахунок ціни. Нічого не замовляється, не доставляється та не тарифікується
freezePricebooleanНіtrue — зафіксувати ціну за вашим договором на 60 секунд. Нічого не замовляється та не тарифікується
quoteIdstringНіРозмістити замовлення за ціною пропозиції (quote), виданої через 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"
        }
    }
}
FieldDescription
unitPriceSunЦіна за одиницю Energy в SUN з урахуванням вашої персональної знижки, якщо вона є
discountВаша персональна знижка (type, value) або null
energyTRX / activationTRX / wouldCostTRXВартість Energy, активації (якщо адреса її потребує) та загальна сума в TRX
activationCheckinactive — адресу буде активовано та внесено до рахунку; active — активація не потрібна; unknown — не вдалося перевірити зараз
alt.<currency>Ті самі суми у валюті вашого договору
fxAtЧас фіксації курсу обміну валют, використаного для сум у валюті вашого договору

Пропозиція з фіксованою ціною (freezePrice: true) ​

Використовуйте пропозицію (quote), щоб зафіксувати ціну за вашим договором перед замовленням.

  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"
        }
    }
}
FieldDescription
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"
    }
}

Замовлення не виконується і кошти не нараховуються. Нові замовлення знову прийматимуться, щойно буде зареєстровано ваш платіж або збільшено ваш ліміт.

Коди помилок для постоплати ​

CodeHTTPDescription
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, перелічених вище, нічого не замовляється та рахунки не виставляються.

Примітки ​

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