POST /apiv2/bandwidth
Оренда TRON bandwidth та її делегування на адресу отримувача на фіксований період (5 хвилин або 1 година).
⚠️ Рівні доступу.
- Акредитовані акаунти орендують будь-яку кількість (до 5000) у межах розміру пулу та максимальних лімітів, зі створенням кількох одночасних замовлень. Акредитація надається службою підтримки Netts.
- Без акредитації ви можете орендувати 400 одиниць один раз — наступне замовлення дозволено лише після закінчення попередньої оренди. Запити на кількість, відмінну від 400, або друге замовлення, поки перше все ще активне, відхиляються.
URL кінцевої точки
POST https://netts.io/apiv2/bandwidthЗаголовки запиту
| Заголовок | Обов'язковий | Опис |
|---|---|---|
| Content-Type | Так | application/json |
| X-API-KEY | Так | Ваш API-ключ із панелі керування Netts |
| X-Real-IP | Так | IP-адреса з вашого білого списку |
| X-Idempotency-Key | Ні | Опціональний згенерований клієнтом ключ (base64) для безпечного повторення запитів без повторного замовлення. Якщо пропущено, сервер згенерує його автоматично |
Тіло запиту
{
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m"
}Параметри
| Параметр | Тип | Обов'язковий | Опис |
|---|---|---|---|
| amount | integer | Так | Кількість одиниць bandwidth для оренди (мінімум: 400, максимум: 5000) |
| receiveAddress | string | Так | TRON-адреса, яка отримає bandwidth (T…, 34 символи, base58) |
| period | string | Так | Тривалість оренди: "5m" (5 хвилин) або "1h" (1 година) |
| trx_send | boolean | Ні | Гарантована транзакція: якщо bandwidth недоступна, на адресу натомість надсилається TRX, щоб транзакція все одно відбулася. Працює лише тоді, коли amount = 400 (в іншому разі ігнорується). За замовчуванням false |
| check | boolean | Ні | Якщо true і отримувач уже має понад 400 bandwidth, замовлення не делегується і кошти не списуються (статус enough). За замовчуванням false |
| test | boolean | Ні | Тестовий прогін. Якщо true, симулюється повний процес виконання замовлення — відповідь повідомляє вам про результат, який би відбувся, і вартість, яку було б списано, — без жодних дій у блокчейні та без списання коштів. За замовчуванням false |
Приклади запитів
Наведені нижче приклади також формують і надсилають
X-Idempotency-Key, щоб випадковий повторний запит не створив друге замовлення. Повні правила див. у розділі Ідемпотентність.
cURL
API_KEY="your_api_key"
ADDR="TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
AMOUNT=1500
PERIOD="5m"
NONCE=$(( $(date +%s) / 2 )) # стабільний для повторних спроб у межах 2-секундного вікна; або ваш власний UUID замовлення
# X-Idempotency-Key = base64( HMAC-SHA256( API_KEY, "addr:amount:period:nonce" ) )
IDEMP=$(printf '%s' "${ADDR}:${AMOUNT}:${PERIOD}:${NONCE}" \
| openssl dgst -sha256 -hmac "$API_KEY" -binary | base64)
curl -X POST https://netts.io/apiv2/bandwidth \
-H "Content-Type: application/json" \
-H "X-API-KEY: $API_KEY" \
-H "X-Real-IP: your_whitelisted_ip" \
-H "X-Idempotency-Key: $IDEMP" \
-d "{\"amount\": $AMOUNT, \"receiveAddress\": \"$ADDR\", \"period\": \"$PERIOD\"}"Python
import time, hmac, hashlib, base64, requests
API_KEY = "your_api_key"
url = "https://netts.io/apiv2/bandwidth"
payload = {
"amount": 1500,
"receiveAddress": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"period": "5m",
}
# X-Idempotency-Key = base64( HMAC-SHA256( API_KEY, "addr:amount:period:nonce" ) )
# Генеруйте ОДИН РАЗ на замовлення і повторно надсилайте те саме значення для кожної повторної спроби.
nonce = str(int(time.time() // 2)) # 2-секундний інтервал; або ваш власний UUID замовлення
message = f"{payload['receiveAddress']}:{payload['amount']}:{payload['period']}:{nonce}"
idem_key = base64.b64encode(
hmac.new(API_KEY.encode(), message.encode(), hashlib.sha256).digest()
).decode()
headers = {
"Content-Type": "application/json",
"X-API-KEY": API_KEY,
"X-Real-IP": "your_whitelisted_ip",
"X-Idempotency-Key": idem_key,
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
detail = data.get("detail", {})
if response.status_code == 200 and detail.get("status") == "completed":
d = detail["data"]
print(f"Order ID: {d['orderId']}")
print(f"Hashes: {d['hash']}") # масив хешів транзакцій делегування
print(f"Bandwidth: {d['bandwidth']} for {d['period']}")
print(f"Cost: {d['paidTRX']} TRX")
else:
print(f"Code: {detail.get('code')} | {detail.get('msg', detail)}")Повний приклад клієнта (Python + cURL) надається разом із сервісним пакетом (handler_bandwidth/doc/client_example/).
Відповідь
Успіх — bandwidth делеговано (200 OK)
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful",
"data": {
"orderId": "B5M<key14>",
"paidTRX": "<amount charged in TRX>",
"fulfilledBy": "bandwidth",
"hash": ["a1b2c3...", "d4e5f6..."],
"bandwidth": 1500,
"period": "5m"
}
}
}Успіх — TRX надіслано замість bandwidth (200 OK, тільки amount=400 + trx_send=true)
Коли в пулі немає bandwidth і параметр trx_send увімкнено, на адресу надсилається TRX, щоб транзакція все одно пройшла. У цьому випадку застосовується фіксована плата, незалежно від запитаного періоду.
{
"detail": {
"code": 10000,
"status": "completed",
"msg": "Successful (sent TRX, bandwidth unavailable)",
"data": {
"orderId": "B5M<key14>",
"paidTRX": "<amount charged in TRX>",
"fulfilledBy": "trx",
"trxSendHash": ["<txid>"],
"hash": [],
"bandwidth": 400,
"period": "5m"
}
}
}Вже достатньо — кошти не списуються (200 OK, тільки з check=true)
{
"detail": {
"code": 10002,
"status": "enough",
"msg": "enough band for 1 transfer",
"data": { "orderId": "B5M<key14>", "paidTRX": 0, "bandwidth": 400, "period": "5m" }
}
}В обробці — зовнішній провайдер (202 Accepted)
Повертається, коли замовлення передається зовнішньому провайдеру асинхронно. Опитуйте кінцеву точку статусу (нижче), використовуючи orderId, доки воно не завершиться.
{
"detail": {
"code": 10001,
"status": "processing",
"msg": "Order accepted, processed by an external provider. Poll the status endpoint.",
"data": { "orderId": "B5M<key14>", "bandwidth": 1500, "period": "5m" }
}
}Тестовий прогін (200 OK, тільки з test=true)
Весь процес виконання замовлення симулюється. testAction повідомляє вам, що мало б статися, а wouldCostTRX — скільки було б списано. Нічого не делегується, TRX не надсилається, кошти не списуються (paidTRX: 0).
{
"detail": {
"code": 10003,
"status": "test",
"msg": "Test run — no on-chain action, no charge",
"data": {
"orderId": "B5M<...>",
"testAction": "would_delegate",
"wouldCostTRX": "<amount that would be charged in TRX>",
"paidTRX": 0,
"bandwidth": 400,
"period": "5m",
"receiverFreeBandwidth": 600
}
}
}Значення testAction: would_delegate (bandwidth було б делеговано), would_trx_send (немає bandwidth, amount=400 + trx_send → було б надіслано TRX), enough (утримувач уже має достатньо, з check=true) або would_error:<reason> (наприклад, no_bandwidth, not_whitelisted).
Поля відповіді
| Поле | Тип | Опис |
|---|---|---|
| detail.code | integer | 10000 делеговано/TRX, 10002 достатньо, 10001 в обробці |
| detail.status | string | completed / enough / processing / failed |
| detail.data.orderId | string | ID замовлення, формат B5M… (5m) / B1H… (1h) — використовуйте його для кінцевої точки статусу |
| detail.data.paidTRX | number | Списана сума в TRX (0, коли enough) |
| detail.data.fulfilledBy | string | bandwidth (делеговано) / trx (надіслано TRX) |
| detail.data.hash | array | Хеші транзакцій делегування (до 10). Завжди масив (порожній для гілки TRX) |
| detail.data.trxSendHash | array | Хеш(і) переказу TRX, присутні лише тоді, коли fulfilledBy = trx |
| detail.data.bandwidth | integer | Делегована кількість одиниць bandwidth |
| detail.data.period | string | Період оренди (5m / 1h) |
Кінцева точка перевірки статусу
GET https://netts.io/apiv2/bandwidth/status/{orderId}Заголовки: X-API-KEY + X-Real-IP (замовлення має належати автентифікованому користувачеві).
| Стан замовлення | HTTP | code | status |
|---|---|---|---|
| Завершено | 200 | 10000 | completed (з hash / trxSendHash) |
| В процесі | 200 | 10001 | processing |
| Вже достатньо | 200 | 10002 | enough |
| Не вдалося | 200 | 5003 | failed |
| Не знайдено / не ваше | 404 | -1 | — |
Кінцева точка відкликання
Добровільно відкличте (скасуйте делегування) bandwidth для одного з ваших делегованих замовлень до закінчення його періоду. Делегування bandwidth скасовується автоматично, і повертається хеш транзакції.
POST https://netts.io/apiv2/bandwidth/reclaim/{orderId}Заголовки: X-API-KEY + X-Real-IP (замовлення має належати автентифікованому користувачеві).
| Стан замовлення | HTTP | code | status | Результат |
|---|---|---|---|---|
| Делеговано → відкликано зараз | 200 | 10004 | reclaimed | reclaimHash (хеші транзакцій скасування делегування) |
| Вже відкликано | 200 | 10004 | reclaimed | reclaimHash + повідомлення "already reclaimed" |
| Не в стані делегування (нічого відкликати) | 400 | 5005 | failed | — |
| Відкликання ще не завершилося | 503 | 5003 | failed | повторіть спробу незабаром |
| Не знайдено / не ваше | 404 | -1 | — | — |
curl -X POST https://netts.io/apiv2/bandwidth/reclaim/B5M<...> \
-H "X-API-KEY: your_api_key" -H "X-Real-IP: your_whitelisted_ip"{
"detail": {
"code": 10004,
"status": "reclaimed",
"msg": "Bandwidth reclaimed",
"data": { "orderId": "B5M<...>", "reclaimHash": ["<txid>"] }
}
}import requests
order_id = "B5M..." # orderId з вашої відповіді на запит оренди
url = f"https://netts.io/apiv2/bandwidth/reclaim/{order_id}"
headers = {"X-API-KEY": "your_api_key", "X-Real-IP": "your_whitelisted_ip"}
resp = requests.post(url, headers=headers)
detail = resp.json()["detail"]
if resp.status_code == 200 and detail["status"] == "reclaimed":
print(f"Reclaimed: {detail['data']['reclaimHash']} ({detail['msg']})")
else:
print(f"Code {detail.get('code')}: {detail.get('msg', detail)}")Вартість оренди не повертається при добровільному достроковому відкликанні — відкликання лише повертає делеговану bandwidth назад до пулу раніше завершення періоду.
Відповіді з помилками
Помилка автентифікації (401)
{ "detail": { "code": -1, "msg": "Invalid API key or IP not in whitelist" } }Недостатній баланс (403)
{ "detail": { "code": 1004, "status": "failed", "msg": "Insufficient funds" } }Помилка валідації (400)
{ "detail": { "code": 5004, "status": "failed", "msg": "Bandwidth amount out of range (400..5000)" } }Помилка делегування / Сервіс недоступний (503)
{ "detail": { "code": 5003, "status": "failed", "msg": "Bandwidth delegation failed" } }Довідник кодів помилок
| Код | Опис | HTTP-статус |
|---|---|---|
10000 | Успіх (делеговано або надіслано TRX) | 200 |
10000 | Успіх (кешована відповідь) | 208 |
10001 | Прийнято, обробляється зовнішнім провайдером | 202 |
10002 | Отримувач уже має достатньо bandwidth (кошти не списано) | 200 |
10003 | Тестовий прогін — попередній перегляд результату та вартості, кошти не списуються (test=true) | 200 |
10004 | Bandwidth відкликано (добровільне скасування делегування) — повернуто reclaimHash | 200 |
- | Дублікат запиту все ще обробляється | 409 |
-1 | Недійсний API-ключ / IP немає в білому списку | 401 |
1004 | Недостатній баланс | 403 |
1005 | Немає адреси платника для користувача | 400 |
5004 | Недійсна кількість/період (валідація) | 400 |
5005 | Нічого відкликати (замовлення не перебуває в стані делегування) | 400 |
5007 | Без акредитації — лише одна оренда одночасно; попереднє замовлення все ще активне (зачекайте на його завершення) | 503 |
5008 | Без акредитації — дозволені замовлення лише на 400 одиниць; для більшої кількості потрібна акредитація | 503 |
5003 | Помилка делегування bandwidth / сервіс недоступний | 503 |
5000 | Внутрішня помилка сервера | 500 |
Обмеження швидкості (Rate Limits)
| Період | Ліміт | Опис |
|---|---|---|
| 1 секунда | 50 запитів | Максимум 50 запитів на секунду з однієї IP-адреси |
Перевищено ліміт запитів (429)
{ "message": "API rate limit exceeded" }Ідемпотентність
Надсилайте необов'язковий заголовок X-Idempotency-Key, щоб випадковий повторний запит не створив друге замовлення — оригінальна відповідь повертається з HTTP 208. Якщо ви не надсилаєте цей заголовок, сервер автоматично генерує ключ із параметрів вашого запиту протягом короткого інтервалу часу.
Як формувати ключ
Ключ являє собою base64( HMAC-SHA256( secret, message ) ) — 44-символьний рядок base64, де:
- secret = ваш API-ключ (
X-API-KEY); - message = поля, об'єднані через
:—receiveAddress:amount:period:nonce.
nonce — це будь-яке значення, яке є стабільним між повторними спробами одного й того самого логічного замовлення, але різним для окремих замовлень — наприклад, UUID, який ви зберігаєте для цього замовлення, або приблизний часовий інтервал. Генеруйте ключ один раз для кожного замовлення та надсилайте точно таке саме значення при кожній повторній спробі.
import hmac, hashlib, base64, time
def make_idempotency_key(api_key, receive_address, amount, period, nonce=None):
if nonce is None:
nonce = str(int(time.time() // 2)) # 2-секундний інтервал; або ваш власний UUID замовлення
message = f"{receive_address}:{amount}:{period}:{nonce}"
digest = hmac.new(api_key.encode(), message.encode(), hashlib.sha256).digest()
return base64.b64encode(digest).decode() # 44-символьний base64# потім надішліть його як заголовок:
-H "X-Idempotency-Key: <base64_key>"Включення period у повідомлення є важливим: оренда для однієї й тієї самої адреси на 5m і на 1h — це різні замовлення, і вони мають створювати різні ключі.
Валідація. Наданий
X-Idempotency-Keyмає бути рядком base64 довжиною 16–64 символи (набір символівA–Z a–z 0–9 + / = _ -). Неправильно сформований або занадто довгий ключ відхиляється з кодом HTTP 400 (code 5004).
| Код статусу | Значення |
|---|---|
| 200 | Успішно оброблено (перший запит) |
| 208 | Вже успішно оброблено — повернуто кешовану відповідь (без повторного списання коштів) |
| 409 | Такий самий запит наразі обробляється — зачекайте, не повторюйте спробу зараз |
Повторення спроби після помилки. Кешуються лише успішні результати (
completed/enough). Якщо попередня спроба закінчилася помилкою або таймаутом (кошти не списувалися), ви можете безпечно повторити спробу з тим самимX-Idempotency-Key— буде виконано повторну спробу замовлення, а не повернення старої помилки. Поки спроба все ще триває, ви отримуєте409; зачекайте і повторіть спробу пізніше.
Примітки
- Рівні доступу: акредитовані акаунти орендують будь-яку кількість у межах лімітів пулу/максимуму з одночасними замовленнями; без акредитації — 400 одиниць один раз (наступне замовлення лише після завершення попередньої оренди). Для отримання акредитації зверніться до служби підтримки Netts.
- Мінімум: 400 одиниць. Максимум: 5000 одиниць на замовлення (поточна конфігурація).
- Періоди:
5m(300 с) та1h(3600 с). Bandwidth автоматично відкликається після закінчення періоду. - Без буфера: делегується рівно запитана кількість.
- hash є масивом: одне замовлення може згенерувати до 10 хешів делегування — повертаються всі.
- Ціноутворення: списується в TRX на основі запитаної кількості та періоду; тарифи можуть відрізнятися залежно від часу доби. Зверніться до служби підтримки щодо актуальних цін.
- Компенсація для малих замовлень (делегування): для замовлень менше 1000 одиниць до вартості додається фіксована сума 0.372 TRX як компенсація за делегування та відкликання в блокчейні. Для замовлень від 1000 одиниць і більше така надбавка відсутня.
- Компенсація за надсилання TRX: коли замовлення виконується шляхом надсилання TRX (
fulfilledBy = trx), замість цього додається фіксована сума 0.268 TRX (компенсація за переказ TRX у блокчейні). - trx_send: лише для
amount = 400; якщо bandwidth недоступна, на адресу надсилається TRX, щоб транзакція все одно відбулася. - check: пропускає делегування (і списання коштів), коли отримувач уже має понад 400 bandwidth.
- Формат ID замовлення:
B5M…(5 хвилин) /B1H…(1 година). - Таймаут відповіді: до ~12 секунд під час очікування делегування; зазвичай 1–2 секунди.