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

POST /apiv2/order1h

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

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ТакКількість 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": "a1b2c3d4e5f6789...",
            "delegateAddress": "TDelegatePoolAddress...",
            "energy": 131050
        }
    }
}

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

ПолеТипОпис
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"
}

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

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

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

До цього ендпоінту застосовуються такі обмеження швидкості (на 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 секунду)
  • Кількість Energy
  • Адреса отримувача
  • API-ключ

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

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

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

Ви можете взяти контроль над ідемпотентністю у свої руки, надіславши заголовок 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()) під час кожного виклику) надає кожній спробі різний ключ, тому повторна спроба після таймауту буде прийнята як друге замовлення і тарифікована знову. Найпростіший правильний вибір — це ID замовлення, який у вас уже є: він існує до першої спроби та зберігається після перезапуску вашого процесу.

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-статус-коди для дублікатів запитів

Статус-кодНазваОпис
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": "b9e67b2412d33c92...",
    "retry_after_seconds": 3
}

Рекомендація: зачекайте вказану кількість секунд у retry_after_seconds перед перевіркою статусу замовлення.

Найкращі практики

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

Примітки

  • 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-адресу