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

POST /apiv2/withdraw ​

Вывод TRX с вашего баланса Netts на любой адрес TRON. Запрос немедленно возвращает номер заказа; фактическая выплата в сети выполняется бэкендом асинхронно (примерно в течение 5 минут). Отслеживайте результат с помощью периодических запросов к эндпоинту статуса или настроив вебхук.

ℹ️ Как это работает. Создание заявки на вывод сразу резервирует сумму с вашего баланса (баланс списывается в момент принятия заказа). Затем фоновый сервис отправляет TRX и помечает заказ как completed или failed. В начальном ответе нет синхронного результата транзакции в сети — сначала вы всегда получаете подтверждение со статусом pending.

URL эндпоинта ​

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

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

ЗаголовокОбязательныйОписание
Content-TypeДаapplication/json
X-API-KEYДаВаш API-ключ из панели управления Netts
X-Real-IPДаIP-адрес из вашего белого списка
X-Idempotency-KeyНетОпциональный сгенерированный клиентом ключ (base64) для безопасных повторных попыток без дублирования вывода. Если не указан, сервер генерирует его автоматически. Это значение становится вашим orderId.

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

json
{
    "amount": 15,
    "address": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}

Параметры ​

ПараметрТипОбязательныйОписание
amountnumberДаСумма брутто в TRX (минимум 3). Комиссия вычитается из этой суммы — получатель получает amount − fee (net).
addressstringДаАдрес назначения TRON (T…, 34 символа, base58).
sub_and_robot_outbooleanНетРежим выплат для роботов/субаккаунтов: применяется комиссия 2 TRX вместо 1 TRX. По умолчанию false.

Комиссия. Фиксированная комиссия удерживается из суммы брутто amount: 1 TRX в обычном режиме или 2 TRX, если sub_and_robot_out = true. Заказ отклоняется, если amount − fee ≤ 0.

Примеры запросов ​

В приведенных ниже примерах также формируется и отправляется заголовок X-Idempotency-Key, чтобы случайный повторный запрос не создал второй вывод средств. Полные правила см. в разделе Идемпотентность.

cURL ​

bash
API_KEY="your_api_key"
ADDR="TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
AMOUNT=15
NONCE=$(( $(date +%s) / 2 ))   # stable for retries within a 2s window; or your own order UUID

# X-Idempotency-Key = base64url( HMAC-SHA256( API_KEY, "addr:amount:nonce" ) )
IDEMP=$(printf '%s' "${ADDR}:${AMOUNT}:${NONCE}" \
  | openssl dgst -sha256 -hmac "$API_KEY" -binary | basenc --base64url | tr -d '=')

curl -X POST https://netts.io/apiv2/withdraw \
  -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, \"address\": \"$ADDR\"}"

Python ​

python
import time, hmac, hashlib, base64, requests

API_KEY = "your_api_key"
url = "https://netts.io/apiv2/withdraw"
payload = {"amount": 15, "address": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}

# X-Idempotency-Key = base64url( HMAC-SHA256( API_KEY, "addr:amount:nonce" ) ), padding stripped.
# Generate ONCE per order and resend the same value on every retry.
nonce = str(int(time.time() // 2))   # 2s bucket; or your own order UUID
message = f"{payload['address']}:{payload['amount']}:{nonce}"
idem_key = base64.urlsafe_b64encode(
    hmac.new(API_KEY.encode(), message.encode(), hashlib.sha256).digest()
).decode().rstrip("=")

headers = {
    "Content-Type": "application/json",
    "X-API-KEY": API_KEY,
    "X-Real-IP": "your_whitelisted_ip",
    "X-Idempotency-Key": idem_key,
}

resp = requests.post(url, headers=headers, json=payload)
detail = resp.json().get("detail", {})

if resp.status_code == 202 and detail.get("status") == "pending":
    d = detail["data"]
    print(f"Order ID: {d['orderId']}")            # use it for the status endpoint / webhook
    print(f"Net to recipient: {d['net']} TRX (fee {d['fee']})")
else:
    print(f"Code {detail.get('code')}: {detail.get('msg', detail)}")

Ответ ​

Принято — вывод поставлен в очередь (202 Accepted) ​

Сумма зарезервирована с вашего баланса, и выплата запланирована. Опрашивайте эндпоинт статуса (или ожидайте вебхук), пока статус не изменится на completed / failed.

json
{
    "detail": {
        "code": 10000,
        "status": "pending",
        "msg": "Withdrawal request accepted, processing within 5 minutes.",
        "data": {
            "orderId": "EXAMPLEorderId0000000000000000000000000000Aa",
            "amount": 15.0,
            "fee": 1.0,
            "net": 14.0,
            "address": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        }
    }
}

Поля ответа ​

ПолеТипОписание
detail.codeinteger10000 принято
detail.statusstringpending
detail.data.orderIdstringНомер заказа — URL-safe строка из 43 символов. Используется для эндпоинта статуса и идентифицирует заказ в данных вебхука.
detail.data.amountnumberЗапрошенная сумма брутто (TRX)
detail.data.feenumberУдержанная комиссия (1 или 2 TRX)
detail.data.netnumberСумма, получаемая адресатом (amount − fee)
detail.data.addressstringАдрес назначения

Эндпоинт статуса ​

GET https://netts.io/apiv2/withdraw/status/{orderId}

Заголовки: X-API-KEY + X-Real-IP (заказ должен принадлежать аутентифицированному пользователю). Значение orderId является URL-safe — передавайте его как есть, без дополнительного URL-кодирования.

Состояние заказаHTTPcodestatus
Завершено (TRX отправлены)20010000completed (с processed_at)
В очереди / отправляется20010001pending
Ошибка2005003failed (с error_message)
Не найден / не принадлежит вам404-1—
json
{
    "detail": {
        "code": 10000,
        "status": "completed",
        "data": {
            "orderId": "EXAMPLEorderId0000000000000000000000000000Aa",
            "amount": 15.0, "fee": 1.0, "net": 14.0,
            "address": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "processed_at": "2026-01-01 00:00:00+00:00"
        }
    }
}

Субаккаунты пользователей ​

Вывод средств для субаккаунтов работает точно так же, как и для обычных пользователей — просто с использованием собственного API-ключа субаккаунта. Субаккаунт вызывает этот же эндпоинт POST /apiv2/withdraw, аутентифицируясь своим ключом; сумма вывода списывается с собственного баланса этого субаккаунта и отправляется на любой address, указанный в запросе. Тот же минимум, та же комиссия (1 TRX), тот же процесс. Отдельного эндпоинта для субаккаунтов нет — каждый аккаунт, основной или субаккаунт, выводит средства только со своего баланса с использованием своего ключа.

Вебхуки ​

Вместо периодического опроса настройте вебхук один раз, и Netts будет отправлять подписанное POST-уведомление, когда каждый из ваших выводов достигнет финального состояния (completed / failed). Вебхук настраивается для каждого пользователя и применяется к выводам этого аккаунта. Если вебхук не настроен, просто опрашивайте эндпоинт статуса.

Настройка / просмотр / удаление ​

POST   https://netts.io/apiv2/withdraw/webhook      # create or update
GET    https://netts.io/apiv2/withdraw/webhook      # view current config (secret is never returned)
DELETE https://netts.io/apiv2/withdraw/webhook      # unsubscribe

Заголовки: X-API-KEY + X-Real-IP.

json
// POST body
{
    "callback_url": "https://your-server.example/netts/withdraw-hook",
    "secret": "your_shared_secret_min_8_chars",
    "enabled": true
}
ПараметрТипОбязательныйОписание
callback_urlstringДаhttp(s) URL (≤ 2048 символов), принимающий POST-запрос
secretstringДаОбщий секретный ключ (8…256 символов), используемый для подписи каждого тела запроса
enabledbooleanНетВключение/выключение доставки без удаления конфигурации. По умолчанию true

GET возвращает { callback_url, enabled, secret_set, updated_at } — сам секретный ключ никогда не возвращается в ответе.

Полезная нагрузка уведомления ​

Netts отправляет запрос POST на ваш callback_url с заголовком X-Netts-Signature: base64( HMAC-SHA256( secret, raw_body ) ) и следующим телом JSON:

json
{
    "orderId": "EXAMPLEorderId0000000000000000000000000000Aa",
    "status": "completed",
    "amount": 15.0,
    "fee": 1.0,
    "net": 14.0,
    "address": "TXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "processed_at": "2026-01-01 00:00:00+00:00",
    "error_message": null
}
  • Поле status принимает значения completed или failed (в случае failed поле error_message будет заполнено).

Проверка подписи ​

Подпись рассчитывается на основе канонического JSON тела запроса: ключи отсортированы, без пробелов (separators=(",", ":")). Вычислите ее аналогичным образом и сравните.

python
import hmac, hashlib, base64, json

def verify(raw_body: bytes, signature_header: str, secret: str) -> bool:
    expected = base64.b64encode(
        hmac.new(secret.encode(), raw_body, hashlib.sha256).digest()
    ).decode()
    return hmac.compare_digest(expected, signature_header)

# Flask example: verify against the EXACT bytes received, then parse.
# if verify(request.get_data(), request.headers["X-Netts-Signature"], SECRET): ...

Всегда выполняйте проверку по исходным полученным байтам. Если вы повторно сериализуете распарсенный JSON, воспроизводите канонический формат: json.dumps(payload, ensure_ascii=False, separators=(",",":"), sort_keys=True).

Гарантии доставки ​

  • Ответьте со статусом HTTP 2xx для подтверждения получения. Любой другой ответ (или таймаут) считается неудачной попыткой.
  • До 3 попыток на заказ в течение окна в 21 минуту с момента создания заказа (интервал повтора ≈ 5 минут). После этого попытки доставки прекращаются — используйте эндпоинт статуса.
  • Доставка дедуплицируется: каждый заказ успешно доставляется максимум один раз.
  • Сделайте ваш обработчик идемпотентным по значению orderId.

Ошибочные ответы ​

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

json
{ "detail": { "code": -1, "msg": "Invalid API key or IP not in whitelist" } }

Недостаточно средств (403) ​

json
{ "detail": { "code": 1004, "status": "failed", "msg": "Insufficient balance: 2.0 < 15 TRX" } }

Уже есть вывод в обработке (409) ​

Вы можете иметь только один незавершенный вывод одновременно на вашем балансе. Дождитесь завершения обработки текущего вывода.

json
{ "detail": { "code": 4090, "status": "failed", "msg": "You have a pending withdrawal. Wait until it is processed." } }

Ошибка валидации (400) ​

json
{ "detail": { "code": 5004, "status": "failed", "msg": "Minimum withdrawal is 3 TRX" } }

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

КодОписаниеHTTP-статус
10000Принято (вывод в очереди) / Завершено (эндпоинт статуса)202 / 200
10001В обработке — в очереди или отправляется (эндпоинт статуса)200
208Дубликат ранее принятого запроса — возвращен закэшированный ответ208
-Такой же запрос все еще обрабатывается (не повторяйте пока)409
4090У вас уже есть активный вывод в обработке409
-1Неверный API-ключ / IP не в белом списке, либо заказ не найден401 / 404
1004Недостаточно средств на балансе403
5004Ошибка валидации (amount < 3, fee ≥ amount, некорректный адрес, некорректный ключ идемпотентности)400
5003Ошибка вывода / сервис недоступен200 (статус) / 503
5000Внутренняя ошибка сервера500

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

Ограничение действует на каждый API-ключ (заголовок X-API-KEY):

ПериодЛимит
1 секунда5 запросов
1 минута150 запросов

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

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

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

Передавайте опциональный заголовок X-Idempotency-Key, чтобы случайный повтор не создал второй вывод — исходный ответ будет возвращен со статусом HTTP 208. Если вы не передаете заголовок, сервер автоматически генерирует ключ на основе параметров запроса в пределах короткого временного окна. Этот ключ также является вашим orderId.

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

Ключ представляет собой base64url( HMAC-SHA256( secret, message ) ) с удаленным заполнением = — URL-safe строку из 43 символов, где:

  • secret = ваш API-ключ (X-API-KEY);
  • message = поля, объединенные через символ : — address:amount:nonce.

Параметр nonce — это любое значение, которое не меняется при повторных попытках одного и того же логического заказа, но различается между разными заказами — например, UUID, который вы сохраняете для этого заказа, или округленный интервал времени. Генерируйте ключ один раз на заказ и отправляйте точно такое же значение при каждой повторной попытке.

python
import hmac, hashlib, base64, time

def make_idempotency_key(api_key, address, amount, nonce=None):
    if nonce is None:
        nonce = str(int(time.time() // 2))   # 2-second bucket; or your own order UUID
    message = f"{address}:{amount}:{nonce}"
    digest = hmac.new(api_key.encode(), message.encode(), hashlib.sha256).digest()
    return base64.urlsafe_b64encode(digest).decode().rstrip("=")  # 43-char URL-safe

Валидация. Переданный X-Idempotency-Key должен содержать от 16 до 64 символов из набора A–Z a–z 0–9 + / = _ -. Некорректный или слишком длинный ключ отклоняется со статусом HTTP 400 (code 5004).

Код статусаЗначение
202Принято (первый запрос)
208Уже принято — возвращен закэшированный ответ (повторный вывод не создается)
409Такой же запрос в данный момент обрабатывается — подождите, пока не повторяйте запрос

Повторная попытка после ошибки. Кэшируются только принятые результаты. Если предыдущая попытка завершилась ошибкой (например, недостаточно средств, ошибка валидации), вы можете безопасно повторить попытку с тем же ключом — запрос будет выполнен заново, а не вернет старую ошибку. Пока попытка все еще находится в процессе выполнения, вы получите 409; подождите и повторите.

Примечания ​

  • Асинхронная выплата. Ответ всегда представляет собой подтверждение со статусом pending; TRX отправляются фоновым процессом, обычно в течение ~5 минут. Используйте эндпоинт статуса или вебхук для получения результата.
  • Баланс резервируется немедленно в момент принятия заказа (а не тогда, когда TRX фактически отправлены).
  • Минимум: 3 TRX. Комиссия: 1 TRX (или 2 TRX при sub_and_robot_out), удерживается из суммы брутто amount; получатель получает net = amount − fee.
  • Только один вывод в обработке одновременно на вашем балансе (code 4090).
  • Субаккаунты выводят средства точно так же, как и обычные пользователи — тот же эндпоинт POST /apiv2/withdraw, те же правила, но с аутентификацией с использованием собственного API-ключа субаккаунта. Субаккаунт выводит свой собственный баланс на любой указанный им address. Отдельного эндпоинта для субаккаунтов нет.
  • Значение orderId — это URL-safe строка из 43 символов; передавайте ее в URL статуса как есть (кодирование не требуется).
  • Вебхуки: настраиваются для пользователя, подписываются заголовком X-Netts-Signature; до 3 попыток в течение 21-минутного окна. Настраиваются через POST /apiv2/withdraw/webhook.