> ## Documentation Index
> Fetch the complete documentation index at: https://wallet-docs.iexexchanger.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Выплаты — отправка платежей

> Оценка комиссии, создание выплаты и отслеживание статуса — запросы, ответы и поля

Выплата — это отправка средств с вашего системного hot-кошелька на адрес получателя.
Платформа сама выбирает кошелёк-источник, подписывает и отправляет транзакцию в сеть, а вы
отслеживаете её по `uuid` или по вашему `order_id`.

Все запросы подписываются (см. [Аутентификация](/authentication)); ответы приходят в
конверте `{ "ok": true, "data": … }`, ошибки — `{ "ok": false, "error": { "code", "message" } }`.
Суммы — всегда строки, чтобы не терять точность.

<Note>
  Создание выплат требует API-ключа со scope `deposit_and_payout`. Ключ, выданный только для
  депозитов (`deposit_only`), получит `403 PERMISSION_DENIED`. Это защита: украденный
  deposit-ключ не сможет вывести средства.
</Note>

## Эндпоинты

| Метод  | Путь                                        | Назначение                           |
| ------ | ------------------------------------------- | ------------------------------------ |
| `POST` | `/v1/public/payouts/fee-estimate`           | оценить комиссию сети (без создания) |
| `POST` | `/v1/public/payouts`                        | создать выплату                      |
| `GET`  | `/v1/public/payouts/{uuid}`                 | получить выплату по uuid             |
| `GET`  | `/v1/public/payouts/by-order-id/{orderId}`  | получить выплату по вашему orderId   |
| `GET`  | `/v1/public/payouts?page=&perPage=&status=` | список (история)                     |

## Рекомендуемый поток

<Steps>
  <Step title="Оцените комиссию">
    Вызовите `POST /v1/public/payouts/fee-estimate`, чтобы показать клиенту комиссию сети до
    подтверждения вывода. Этот вызов ничего не создаёт.
  </Step>

  <Step title="Создайте выплату">
    `POST /v1/public/payouts` с уникальным `orderId`. В ответе придёт `uuid` и стартовый
    `status` (`queued` при авто-одобрении или `pending_approval`, если нужно ручное одобрение).
  </Step>

  <Step title="Отслеживайте статус">
    Слушайте [вебхуки](/webhooks/overview) (`payout.broadcasted`, `payout.confirmed`,
    `payout.failed`) или периодически опрашивайте `GET /v1/public/payouts/{uuid}`.
    Финальный успешный статус — `confirmed`.
  </Step>
</Steps>

***

## Оценить комиссию

`POST /v1/public/payouts/fee-estimate` — узнать комиссию сети перед созданием выплаты.
Удобно для предпросмотра суммы к списанию и UX «вы получите …».

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

<ParamField body="assetCode" type="string" required>Код актива, например `USDT_TRC20` или `TON`.</ParamField>
<ParamField body="destinationAddress" type="string" required>Адрес получателя (макс. 255 символов).</ParamField>
<ParamField body="amount" type="string" required>Сумма выплаты строкой, например `"50.00"`.</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  TS=$(date +%s)
  BODY='{"assetCode":"USDT_TRC20","destinationAddress":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","amount":"50.00"}'
  SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | sed 's/^.* //')
  curl -X POST https://wallet.your-exchange.com/v1/public/payouts/fee-estimate \
    -H "X-Api-Id: $API_ID" -H "X-Timestamp: $TS" -H "X-Signature: $SIG" \
    -H "Content-Type: application/json" -d "$BODY"
  ```

  ```javascript Node.js theme={null}
  import crypto from 'node:crypto';

  const body = {
    assetCode: 'USDT_TRC20',
    destinationAddress: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
    amount: '50.00',
  };
  const raw = JSON.stringify(body);
  const ts = Math.floor(Date.now() / 1000).toString();
  const sig = crypto.createHmac('sha256', API_SECRET).update(`${ts}.${raw}`).digest('hex');

  const res = await fetch('https://wallet.your-exchange.com/v1/public/payouts/fee-estimate', {
    method: 'POST',
    headers: {
      'X-Api-Id': API_ID,
      'X-Timestamp': ts,
      'X-Signature': sig,
      'Content-Type': 'application/json',
    },
    body: raw,
  });
  const { data } = await res.json();
  console.log(data.networkFee, data.resource);
  ```
</CodeGroup>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "ok": true,
    "data": {
      "networkFee": "27.0",
      "resource": { "kind": "energy", "amount": 65000 },
      "estimatedConfirmationSeconds": 60
    }
  }
  ```
</ResponseExample>

### Поля ответа

<ResponseField name="networkFee" type="string">
  Оценка комиссии сети в native-единицах сети (для TRC-20 — в TRX, для Jetton-выплат TON — в TON).
</ResponseField>

<ResponseField name="resource" type="object">
  Дополнительный ресурс сети: `kind` — `energy` (TRON) / `gas` (EVM) / `bytes` (UTXO) / `none`;
  `amount` — оценка нужного количества этого ресурса.
</ResponseField>

<ResponseField name="estimatedConfirmationSeconds" type="number">
  Грубая оценка времени до подтверждения (в секундах).
</ResponseField>

<Tip>
  Оценка комиссии не резервирует средства и не гарантирует точную итоговую комиссию: реальная
  стоимость зависит от состояния сети на момент отправки. Используйте её для предпросмотра, а не
  как фиксированную величину.
</Tip>

***

## Создать выплату

`POST /v1/public/payouts`

Создаёт выплату на указанный адрес. Операция идемпотентна по паре `(сайт, order_id)` и,
опционально, по заголовку `X-Idempotency-Key`. В зависимости от настроенных политик выплата
может уйти в очередь сразу или потребовать ручного одобрения оператором.

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

<ParamField body="orderId" type="string" required>
  Ваш идентификатор выплаты (1–255 символов). В строгом режиме (по умолчанию) должен быть
  уникальным в рамках сайта: повтор уже использованного `orderId` (в том числе с другим
  `assetCode`) вернёт `409 DUPLICATE_ORDER_ID` — защита от случайной двойной выплаты. Для
  безопасных ретраев используйте `X-Idempotency-Key` (см. [Идемпотентность](/idempotency)).
</ParamField>

<ParamField body="assetCode" type="string" required>Код актива, например `USDT_TRC20` или `TON` (макс. 64 символа).</ParamField>
<ParamField body="destinationAddress" type="string" required>Адрес получателя (макс. 255 символов). Проверяется и нормализуется по правилам сети.</ParamField>

<ParamField body="destinationMemo" type="string">
  Memo/comment для memo-based сетей (например TON Jetton). Для account-based сетей (TRON, EVM)
  не используется. Опционально, макс. 255 символов.
</ParamField>

<ParamField body="amount" type="string" required>
  Сумма выплаты строкой, например `"50.00"`. Число знаков после запятой не должно превышать
  точность актива (`USDT_TRC20` — 6, `TON` — 9), иначе `INVALID_AMOUNT` / `VALIDATION_FAILED`.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  TS=$(date +%s)
  BODY='{"orderId":"order_77","assetCode":"USDT_TRC20","destinationAddress":"TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t","amount":"50.00"}'
  SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | sed 's/^.* //')
  curl -X POST https://wallet.your-exchange.com/v1/public/payouts \
    -H "X-Api-Id: $API_ID" -H "X-Timestamp: $TS" -H "X-Signature: $SIG" \
    -H "X-Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \
    -H "Content-Type: application/json" -d "$BODY"
  ```

  ```javascript Node.js theme={null}
  import crypto from 'node:crypto';
  import { randomUUID } from 'node:crypto';

  const body = {
    orderId: 'order_77',
    assetCode: 'USDT_TRC20',
    destinationAddress: 'TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t',
    amount: '50.00',
  };
  const raw = JSON.stringify(body);
  const ts = Math.floor(Date.now() / 1000).toString();
  const sig = crypto.createHmac('sha256', API_SECRET).update(`${ts}.${raw}`).digest('hex');

  const res = await fetch('https://wallet.your-exchange.com/v1/public/payouts', {
    method: 'POST',
    headers: {
      'X-Api-Id': API_ID,
      'X-Timestamp': ts,
      'X-Signature': sig,
      'X-Idempotency-Key': randomUUID(),
      'Content-Type': 'application/json',
    },
    body: raw,
  });
  const { ok, data, error } = await res.json();
  ```
</CodeGroup>

Пример для memo-based сети (TON Jetton) — с `destinationMemo`:

```json TON Jetton theme={null}
{
  "orderId": "order_78",
  "assetCode": "USDT_TON",
  "destinationAddress": "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
  "destinationMemo": "WP-90AB12CD",
  "amount": "25.00"
}
```

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "c1d2e3f4-5678-90ab-cdef-1234567890ab",
      "orderId": "order_77",
      "status": "queued",
      "assetCode": "USDT_TRC20",
      "destinationAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "destinationMemo": null,
      "amount": "50.000000",
      "requiresApproval": false,
      "txHash": null,
      "confirmations": null,
      "requiredConfirmations": null,
      "networkStatus": null,
      "explorerTxUrl": null,
      "failReason": null,
      "approvedAt": null,
      "broadcastedAt": null,
      "confirmedAt": null,
      "createdAt": "2026-06-02T20:50:00.000Z",
      "updatedAt": "2026-06-02T20:50:00.000Z"
    }
  }
  ```
</ResponseExample>

<Warning>
  Если в ответе `"requiresApproval": true` и `"status": "pending_approval"` — выплата ждёт
  **ручного одобрения** оператором в личном кабинете и уйдёт в сеть только после него. Это
  защита от ошибочных крупных выводов и срабатывание политик (лимиты, белый список адресов,
  velocity-проверки). Отслеживайте статус через `GET` или вебхуки.
</Warning>

***

## Получить выплату

`GET /v1/public/payouts/{uuid}` — по `uuid` из ответа на создание, либо
`GET /v1/public/payouts/by-order-id/{orderId}` — по вашему `order_id`.
Оба возвращают один и тот же объект. On-chain поля (`txHash`, `confirmations`, `networkStatus`,
`explorerTxUrl`, `broadcastedAt`) заполняются после отправки транзакции в сеть.

<CodeGroup>
  ```bash cURL (по uuid) theme={null}
  TS=$(date +%s)
  SIG=$(printf '%s.' "$TS" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | sed 's/^.* //')
  curl https://wallet.your-exchange.com/v1/public/payouts/c1d2e3f4-5678-90ab-cdef-1234567890ab \
    -H "X-Api-Id: $API_ID" -H "X-Timestamp: $TS" -H "X-Signature: $SIG"
  ```

  ```bash cURL (по order_id) theme={null}
  TS=$(date +%s)
  SIG=$(printf '%s.' "$TS" | openssl dgst -sha256 -hmac "$API_SECRET" -hex | sed 's/^.* //')
  curl https://wallet.your-exchange.com/v1/public/payouts/by-order-id/order_77 \
    -H "X-Api-Id: $API_ID" -H "X-Timestamp: $TS" -H "X-Signature: $SIG"
  ```
</CodeGroup>

<Note>
  Это GET-запрос с пустым телом, поэтому подписывается строка `{timestamp}.` (timestamp, затем
  точка). Подробнее — в разделе [Аутентификация](/authentication).
</Note>

<ResponseExample>
  ```json 200 OK — отправлена в сеть (status: broadcasted) theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "c1d2e3f4-5678-90ab-cdef-1234567890ab",
      "orderId": "order_77",
      "status": "broadcasted",
      "assetCode": "USDT_TRC20",
      "destinationAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "destinationMemo": null,
      "amount": "50.000000",
      "requiresApproval": false,
      "txHash": "f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9",
      "confirmations": 12,
      "requiredConfirmations": 19,
      "networkStatus": "mempool",
      "explorerTxUrl": "https://tronscan.org/#/transaction/f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9",
      "failReason": null,
      "approvedAt": null,
      "broadcastedAt": "2026-06-02T20:51:10.000Z",
      "confirmedAt": null,
      "createdAt": "2026-06-02T20:50:00.000Z",
      "updatedAt": "2026-06-02T20:51:10.000Z"
    }
  }
  ```
</ResponseExample>

### Поля ответа

<ResponseField name="uuid" type="string">Публичный идентификатор выплаты (UUID).</ResponseField>
<ResponseField name="orderId" type="string">Ваш `order_id`, переданный при создании.</ResponseField>
<ResponseField name="status" type="string">Бизнес-статус выплаты. Полный набор — [Статусы выплаты](/payouts/statuses).</ResponseField>
<ResponseField name="assetCode" type="string">Код актива.</ResponseField>
<ResponseField name="destinationAddress" type="string">Адрес получателя (в нормализованной форме сети).</ResponseField>
<ResponseField name="destinationMemo" type="string | null">Memo получателя для memo-based сетей, иначе `null`.</ResponseField>
<ResponseField name="amount" type="string">Сумма выплаты строкой, отформатированная под точность актива.</ResponseField>
<ResponseField name="requiresApproval" type="boolean">Требуется ли ручное одобрение оператором.</ResponseField>
<ResponseField name="txHash" type="string | null">Хеш исходящей транзакции. `null` до отправки в сеть.</ResponseField>
<ResponseField name="confirmations" type="number | null">Текущее число подтверждений сети. `null` до отправки.</ResponseField>
<ResponseField name="requiredConfirmations" type="number | null">Сколько подтверждений нужно для финализации (из настроек актива). `null` до отправки.</ResponseField>
<ResponseField name="networkStatus" type="string | null">On-chain статус исходящей tx: `pending` → `mempool` → `confirmed` | `fail`. `null` до отправки.</ResponseField>
<ResponseField name="explorerTxUrl" type="string | null">Ссылка на транзакцию в блок-эксплорере. `null` пока нет хеша.</ResponseField>
<ResponseField name="failReason" type="string | null">Причина для терминальных статусов `failed` / `rejected` / `cancelled`, иначе `null`.</ResponseField>
<ResponseField name="approvedAt" type="string | null">Когда выплата одобрена оператором (ISO-8601). `null` при авто-одобрении или до одобрения.</ResponseField>
<ResponseField name="broadcastedAt" type="string | null">Когда транзакция отправлена в сеть (ISO-8601). `null` до отправки.</ResponseField>
<ResponseField name="confirmedAt" type="string | null">Когда выплата подтверждена сетью (ISO-8601). `null` до подтверждения.</ResponseField>
<ResponseField name="createdAt" type="string">Время создания выплаты (ISO-8601).</ResponseField>
<ResponseField name="updatedAt" type="string">Время последнего обновления (ISO-8601).</ResponseField>

<Note>
  Адрес-источник (наш hot-кошелёк), внутренние идентификаторы и приватные ключи наружу
  **не отдаются** — только то, что нужно для отслеживания исходящей транзакции.
</Note>

***

## Список выплат

`GET /v1/public/payouts?page=1&perPage=20&status=confirmed`

История выплат сайта с пагинацией. Доступна только тем выплатам, что принадлежат сайту
вызывающего ключа.

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

<ParamField query="page" type="number" default="1">Номер страницы (с 1).</ParamField>
<ParamField query="perPage" type="number" default="20">Размер страницы (макс. 100).</ParamField>

<ParamField query="status" type="string">
  Фильтр по статусу. Одно значение (`?status=confirmed`) или несколько через запятую
  (`?status=queued,broadcasted`). Неизвестные значения отбрасываются.
</ParamField>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "ok": true,
    "data": {
      "items": [
        {
          "uuid": "c1d2e3f4-5678-90ab-cdef-1234567890ab",
          "orderId": "order_77",
          "status": "confirmed",
          "assetCode": "USDT_TRC20",
          "destinationAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
          "destinationMemo": null,
          "amount": "50.000000",
          "requiresApproval": false,
          "txHash": "f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9",
          "confirmations": 19,
          "requiredConfirmations": 19,
          "networkStatus": "confirmed",
          "explorerTxUrl": "https://tronscan.org/#/transaction/f0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c9b8a7f6e5d4c3b2a1f0e9",
          "failReason": null,
          "approvedAt": null,
          "broadcastedAt": "2026-06-02T20:51:10.000Z",
          "confirmedAt": "2026-06-02T20:53:40.000Z",
          "createdAt": "2026-06-02T20:50:00.000Z",
          "updatedAt": "2026-06-02T20:53:40.000Z"
        }
      ],
      "meta": { "page": 1, "perPage": 20, "total": 58 }
    }
  }
  ```
</ResponseExample>

`meta.total` — общее число записей по всем страницам (с учётом фильтра по статусу).

***

## Частые ошибки

| HTTP | Код                              | Причина                                                                                                                           |
| ---- | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| 403  | `PERMISSION_DENIED`              | Ключ выдан только для депозитов (`deposit_only`) — создание выплат запрещено. Используйте ключ со scope `deposit_and_payout`.     |
| 409  | `DUPLICATE_ORDER_ID`             | `orderId` уже использован для этого сайта (строгий режим). Для ретраев применяйте `X-Idempotency-Key`.                            |
| 404  | `INVALID_ASSET`                  | Указанный `assetCode` не найден.                                                                                                  |
| 409  | `NETWORK_DISABLED`               | Выплаты по этому активу выключены или актив неактивен.                                                                            |
| 400  | `INVALID_ADDRESS`                | Адрес получателя не проходит валидацию для сети актива.                                                                           |
| 400  | `INVALID_AMOUNT`                 | Сумма не положительная или с недопустимым числом знаков после запятой.                                                            |
| 409  | `AMOUNT_BELOW_MINIMUM`           | Сумма ниже минимальной выплаты для актива.                                                                                        |
| 400  | `PAYOUT_DESTINATION_BLACKLISTED` | Адрес получателя в чёрном списке — выплата запрещена.                                                                             |
| 400  | `PAYOUT_WHITELIST_REJECT`        | Адрес не в белом списке вывода (режим enforced).                                                                                  |
| 400  | `PAYOUT_VELOCITY_REJECT`         | Превышены velocity-лимиты (частота/объём выплат).                                                                                 |
| 404  | `PAYOUT_NOT_FOUND`               | Выплата с таким `uuid` / `orderId` не найдена для этого сайта.                                                                    |
| 403  | `LICENSE_REQUIRED`               | Лицензия инстанса неактивна — создание новых выплат недоступно. Уже одобренные и поставленные в очередь выплаты не затрагиваются. |

Полный справочник кодов — на странице [Ошибки](/errors). Ошибки аутентификации
(`UNAUTHORIZED`, `INVALID_SIGNATURE`, `TIMESTAMP_SKEW`, `IP_NOT_WHITELISTED`) описаны в
[Аутентификации](/authentication).

## Частые вопросы

<AccordionGroup>
  <Accordion title="Чем отличается uuid от order_id?">
    `uuid` выдаёт платформа — это публичный идентификатор выплаты на нашей стороне. `order_id`
    задаёте вы — это ваш ключ, по которому работает идемпотентность и поиск через
    `by-order-id/{orderId}`. Храните оба.
  </Accordion>

  <Accordion title="Как безопасно повторить запрос при таймауте?">
    Передавайте `X-Idempotency-Key` (UUID) при создании. Повтор того же запроса с тем же ключом
    вернёт уже созданную выплату, а не создаст вторую. Без идемпотентного ключа повтор с тем же
    `orderId` в строгом режиме завершится `409 DUPLICATE_ORDER_ID`. См. [Идемпотентность](/idempotency).
  </Accordion>

  <Accordion title="Выплата зависла в pending_approval — что делать?">
    Она ждёт ручного одобрения оператором в личном кабинете (сработала политика одобрения,
    лимит, белый список адресов или velocity-проверка). После одобрения статус сменится на
    `approved` → `queued` и далее по потоку. Отслеживайте через вебхук или `GET`.
  </Accordion>

  <Accordion title="Нужно ли вызывать fee-estimate перед каждой выплатой?">
    Нет, это необязательный шаг. Он удобен для предпросмотра комиссии в UI. Оценка не резервирует
    средства и не фиксирует точную итоговую комиссию.
  </Accordion>

  <Accordion title="Когда txHash станет доступен?">
    После того как транзакция подписана и отправлена в сеть (статус `broadcasted`). До этого
    `txHash`, `confirmations`, `networkStatus` и `explorerTxUrl` равны `null`.
  </Accordion>

  <Accordion title="Что нужно для выплат в TON (Jetton)?">
    TON — memo-based сеть: помимо `destinationAddress` передавайте `destinationMemo` (comment),
    если получателю требуется метка платежа. Сумма указывается с точностью до 9 знаков.
  </Accordion>
</AccordionGroup>

## Смотрите также

* [Статусы выплаты](/payouts/statuses) — жизненный цикл и какие вебхуки срабатывают.
* [Вебхуки](/webhooks/overview) — события `payout.broadcasted`, `payout.confirmed`, `payout.failed`.
* [Идемпотентность](/idempotency) — `order_id` и `X-Idempotency-Key`.
* [Ошибки](/errors) — полный справочник кодов ответа.
