> ## 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.

# Депозиты — приём платежей

> Создание депозита, отслеживание, AML-скрин, примеры запросов и ответов

Депозит — это запрос на приём средств от вашего клиента. Платформа создаёт уникальную
цель приёма (адрес, а для memo-сетей — общий адрес плюс уникальный `memo`), мониторит
сеть на входящую транзакцию и сообщает об оплате двумя способами: через статусы (которые
вы читаете GET-запросами) и через [webhooks](/webhooks/overview), которые платформа сама
шлёт на ваш `callback_url`.

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

<Info>
  Во всех примерах ниже базовый URL и идентификатор ключа одни и те же:
  `https://wallet.your-exchange.com` и `X-Api-Id: pk_live_a1b2c3d4`. Подставьте свои
  значения из админ-кабинета.
</Info>

## Эндпоинты

| Метод  | Путь                                            | Назначение                                           |
| ------ | ----------------------------------------------- | ---------------------------------------------------- |
| `POST` | `/v1/public/deposits`                           | создать депозит                                      |
| `GET`  | `/v1/public/deposits`                           | список (история), с пагинацией и фильтром по статусу |
| `GET`  | `/v1/public/deposits/{uuid}`                    | получить депозит по его `uuid`                       |
| `GET`  | `/v1/public/deposits/by-order-id/{orderId}`     | получить депозит по вашему `order_id`                |
| `GET`  | `/v1/public/deposits/{uuid}/aml`                | AML-данные (source-of-funds) по `uuid`               |
| `GET`  | `/v1/public/deposits/by-order-id/{orderId}/aml` | AML-данные по вашему `order_id`                      |

## Адрес или адрес + memo: TON против TRON/EVM

Платформа поддерживает две модели идентификации входящего платежа. От модели зависит, что
именно нужно показать вашему клиенту для оплаты.

<CardGroup cols={2}>
  <Card title="Address-based (TRON, EVM)" icon="wallet">
    На каждый депозит выдаётся **уникальный адрес**. В ответе `memo` равен `null`. Клиент
    переводит средства на `data.address` — этого достаточно, чтобы платёж был привязан к
    нужной заявке.
  </Card>

  <Card title="Memo-based (TON)" icon="tag">
    Используется **общий приёмный адрес** плюс **уникальный `memo`** (он же comment/tag).
    В ответе `memo` не равен `null`. Клиент обязан указать и `data.address`, и `data.memo` —
    без memo платёж невозможно сопоставить с заявкой.
  </Card>
</CardGroup>

<Warning>
  Для memo-сетей (TON) memo обязателен. Если клиент отправит средства на общий адрес без
  memo или с неверным memo, платёж не будет автоматически привязан к депозиту. Всегда
  проверяйте `data.memo !== null` и показывайте memo как отдельное обязательное поле.
</Warning>

***

## Создать депозит

`POST /v1/public/deposits`

Создаёт новый депозит и возвращает реквизиты для оплаты. Вызывайте этот эндпоинт в момент,
когда клиент на стороне обменника выбрал валюту и готов платить.

Операция идемпотентна по комбинации `(site, order_id, asset)` и, опционально, по заголовку
`X-Idempotency-Key`. Подробнее — в разделе [Идемпотентность](/idempotency).

<Note>
  Создание новых депозитов требует активной лицензии инстанса. Если лицензия не активирована,
  эндпоинт вернёт `403 LICENSE_REQUIRED`. Уже идущие депозиты при этом не затрагиваются.
</Note>

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

<ParamField body="assetCode" type="string" required>
  Код актива, например `USDT_TRC20`, `TRX`, `USDT_TON`. Полный список доступных активов —
  `GET /v1/public/assets`. Максимум 64 символа.
</ParamField>

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

<ParamField body="expectedAmount" type="string">
  Ожидаемая сумма как decimal-строка, например `"100.50"`. **Опционально** — если не
  передать, берётся минимальная сумма приёма актива (`asset.minDepositAmount`). Значение
  `"0"` означает «принять любую сумму». Число знаков после запятой не должно превышать
  точность актива, иначе вернётся `400 AMOUNT_TOO_MANY_DECIMALS`.
</ParamField>

<ParamField body="comment" type="string">
  Опциональная заметка к депозиту (видна только вам в админ-кабинете). Максимум 1024 символа.
</ParamField>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://wallet.your-exchange.com/v1/public/deposits \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1769990400" \
    -H "X-Signature: 9b1f...c0e2" \
    -H "Content-Type: application/json" \
    -d '{
      "assetCode": "USDT_TRC20",
      "orderId": "WX-1042",
      "expectedAmount": "100.50"
    }'
  ```

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

  const BASE = 'https://wallet.your-exchange.com';
  const API_ID = 'pk_live_a1b2c3d4';
  const API_SECRET = process.env.WALLET_API_SECRET; // никогда не уходит в сеть

  const body = JSON.stringify({
    assetCode: 'USDT_TRC20',
    orderId: 'WX-1042',
    expectedAmount: '100.50',
  });

  const ts = Math.floor(Date.now() / 1000).toString();
  const message = `${ts}.${body}`; // timestamp + "." + raw body
  const signature = crypto
    .createHmac('sha256', API_SECRET)
    .update(message)
    .digest('hex'); // lowercase hex

  const res = await fetch(`${BASE}/v1/public/deposits`, {
    method: 'POST',
    headers: {
      'X-Api-Id': API_ID,
      'X-Timestamp': ts,
      'X-Signature': signature,
      'Content-Type': 'application/json',
      'X-Idempotency-Key': crypto.randomUUID(), // опционально
    },
    body,
  });

  const { ok, data, error } = await res.json();
  if (!ok) throw new Error(`${error.code}: ${error.message}`);
  console.log('Платить на адрес:', data.address, 'memo:', data.memo);
  ```
</CodeGroup>

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
      "orderId": "WX-1042",
      "address": "TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
      "memo": null,
      "assetCode": "USDT_TRC20",
      "expectedAmount": "100.50",
      "status": "check",
      "expiresAt": "2026-06-26T21:30:00.000Z",
      "explorerAddressUrl": "https://tronscan.org/#/address/TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
      "transaction": null
    }
  }
  ```
</ResponseExample>

Пример ответа для memo-сети (TON) — обратите внимание на непустой `memo`:

<ResponseExample>
  ```json 201 Created (TON, memo-based) theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "2b7d9e44-1a3c-4f88-bc05-6d2e9f0a1b34",
      "orderId": "WX-1043",
      "address": "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
      "memo": "WP-1A2B3C4D",
      "assetCode": "USDT_TON",
      "expectedAmount": "50",
      "status": "check",
      "expiresAt": "2026-06-26T21:35:00.000Z",
      "explorerAddressUrl": "https://tonviewer.com/EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
      "transaction": null
    }
  }
  ```
</ResponseExample>

<Note>
  Покажите клиенту `data.address`, а если `data.memo` не равен `null` (memo-сети) — ещё и
  `data.memo` как обязательное поле. `transaction` равен `null` до тех пор, пока в сети не
  будет замечена входящая транзакция.
</Note>

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

Ответ создания и все GET-эндпоинты (кроме AML) возвращают один и тот же объект депозита:

<ResponseField name="uuid" type="string">
  Публичный идентификатор депозита. Используйте его в `GET /v1/public/deposits/{uuid}`.
</ResponseField>

<ResponseField name="orderId" type="string">
  Ваш `order_id` (label). Если вы его не передавали, здесь будет авто-сгенерированный код.
</ResponseField>

<ResponseField name="address" type="string">
  Адрес для оплаты. Для memo-сетей — общий приёмный адрес (используется вместе с `memo`).
</ResponseField>

<ResponseField name="memo" type="string | null">
  Memo/comment. Не равен `null` и обязателен для memo-сетей (TON); `null` для address-based
  сетей (TRON, EVM).
</ResponseField>

<ResponseField name="assetCode" type="string">
  Код актива депозита.
</ResponseField>

<ResponseField name="expectedAmount" type="string">
  Ожидаемая сумма (строка). `"0"` означает, что принимается любая сумма.
</ResponseField>

<ResponseField name="status" type="string">
  Бизнес-статус депозита. Полный набор и переходы — [Статусы депозита](/deposits/statuses).
</ResponseField>

<ResponseField name="expiresAt" type="string">
  ISO-8601. До какого момента сеть мониторится на оплату. После этого момента неоплаченный
  депозит уходит в `expired`.
</ResponseField>

<ResponseField name="explorerAddressUrl" type="string | null">
  Ссылка на адрес в блок-эксплорере (`null`, если для актива не настроен шаблон).
</ResponseField>

<ResponseField name="transaction" type="object | null">
  On-chain данные входящей транзакции. `null`, пока депозит не получил ни одной транзакции.

  <Expandable title="поля transaction">
    <ResponseField name="networkStatus" type="string">
      Статус транзакции в сети: `pending` → `mempool` → `confirmed` | `fail`.
    </ResponseField>

    <ResponseField name="receivedAmount" type="string | null">
      Фактически полученная сумма (строка). `null`, пока tx не подтверждена.
    </ResponseField>

    <ResponseField name="txhash" type="string | null">
      Хеш входящей транзакции.
    </ResponseField>

    <ResponseField name="confirmations" type="number | null">
      Текущее число подтверждений сети.
    </ResponseField>

    <ResponseField name="requiredConfirmations" type="number | null">
      Сколько подтверждений требуется для финализации (`asset.minConfirmations`).
    </ResponseField>

    <ResponseField name="blockNumber" type="string | null">
      Номер блока (строка, т.к. может превышать `Number.MAX_SAFE_INTEGER`). `null`, пока tx
      в mempool.
    </ResponseField>

    <ResponseField name="explorerTxUrl" type="string | null">
      Ссылка на транзакцию в блок-эксплорере.
    </ResponseField>

    <ResponseField name="detectedAt" type="string | null">
      ISO-8601. Когда транзакция впервые замечена в сети.
    </ResponseField>

    <ResponseField name="paidAt" type="string | null">
      ISO-8601. Когда депозит финализирован (`paid` / `paid_over` / `wrong_amount`). `null`,
      пока не финализирован.
    </ResponseField>
  </Expandable>
</ResponseField>

***

## Получить депозит

`GET /v1/public/deposits/{uuid}` — по `uuid` из ответа на создание.

`GET /v1/public/deposits/by-order-id/{orderId}` — по вашему `order_id`.

Оба эндпоинта возвращают один и тот же объект депозита. Поле `transaction` заполняется, как
только в сети замечена входящая tx, и обновляется с каждым новым подтверждением. Опрашивайте
эндпоинт периодически либо опирайтесь на [webhooks](/webhooks/overview), чтобы не дёргать
API лишний раз.

<CodeGroup>
  ```bash cURL (по uuid) theme={null}
  curl https://wallet.your-exchange.com/v1/public/deposits/8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1769990500" \
    -H "X-Signature: 4d8e...91af"
  ```

  ```bash cURL (по order_id) theme={null}
  curl https://wallet.your-exchange.com/v1/public/deposits/by-order-id/WX-1042 \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1769990500" \
    -H "X-Signature: 4d8e...91af"
  ```
</CodeGroup>

<Note>
  Это GET-запросы без тела, поэтому подписываемое сообщение —
  `X-Timestamp + "." + ""`, то есть просто `"1769990500."` (timestamp и точка).
  См. [Аутентификация](/authentication).
</Note>

<CodeGroup>
  ```json В процессе (status: process) theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
      "orderId": "WX-1042",
      "address": "TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
      "memo": null,
      "assetCode": "USDT_TRC20",
      "expectedAmount": "100.50",
      "status": "process",
      "expiresAt": "2026-06-26T21:30:00.000Z",
      "explorerAddressUrl": "https://tronscan.org/#/address/TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
      "transaction": {
        "networkStatus": "mempool",
        "receivedAmount": "100.50",
        "txhash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
        "confirmations": 3,
        "requiredConfirmations": 19,
        "blockNumber": null,
        "explorerTxUrl": "https://tronscan.org/#/transaction/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
        "detectedAt": "2026-06-26T20:35:12.000Z",
        "paidAt": null
      }
    }
  }
  ```

  ```json Оплачено (status: paid) theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
      "orderId": "WX-1042",
      "address": "TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
      "memo": null,
      "assetCode": "USDT_TRC20",
      "expectedAmount": "100.50",
      "status": "paid",
      "expiresAt": "2026-06-26T21:30:00.000Z",
      "explorerAddressUrl": "https://tronscan.org/#/address/TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
      "transaction": {
        "networkStatus": "confirmed",
        "receivedAmount": "100.50",
        "txhash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
        "confirmations": 19,
        "requiredConfirmations": 19,
        "blockNumber": "65123456",
        "explorerTxUrl": "https://tronscan.org/#/transaction/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
        "detectedAt": "2026-06-26T20:35:12.000Z",
        "paidAt": "2026-06-26T20:41:05.000Z"
      }
    }
  }
  ```
</CodeGroup>

<Tip>
  Прогресс подтверждений считается как `transaction.confirmations` / `transaction.requiredConfirmations`
  (например `3 / 19`). Чтобы отличить точную оплату от переплаты или недоплаты, сравните
  `transaction.receivedAmount` с `expectedAmount` — подробности в
  [Статусах депозита](/deposits/statuses).
</Tip>

***

## Список депозитов

`GET /v1/public/deposits?page=1&perPage=20&status=paid`

Возвращает историю депозитов вашего сайта в обратном хронологическом порядке. Каждый элемент
имеет ту же форму, что и одиночный депозит.

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

<ParamField query="page" type="integer" default="1">
  Номер страницы, начиная с 1.
</ParamField>

<ParamField query="perPage" type="integer" default="20">
  Размер страницы. Минимум 1, максимум 100.
</ParamField>

<ParamField query="status" type="string">
  Фильтр по статусу: одно значение (`?status=paid`) или несколько через запятую
  (`?status=paid,paid_over`). Допустимые значения — из набора бизнес-статусов депозита
  (см. [Статусы депозита](/deposits/statuses)). Неизвестные значения молча игнорируются.
</ParamField>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "ok": true,
    "data": {
      "items": [
        {
          "uuid": "8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
          "orderId": "WX-1042",
          "address": "TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
          "memo": null,
          "assetCode": "USDT_TRC20",
          "expectedAmount": "100.50",
          "status": "paid",
          "expiresAt": "2026-06-26T21:30:00.000Z",
          "explorerAddressUrl": "https://tronscan.org/#/address/TKh9aBcDeFgHiJkLmNoPqRsTuVwXyZ12c4",
          "transaction": {
            "networkStatus": "confirmed",
            "receivedAmount": "100.50",
            "txhash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
            "confirmations": 19,
            "requiredConfirmations": 19,
            "blockNumber": "65123456",
            "explorerTxUrl": "https://tronscan.org/#/transaction/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
            "detectedAt": "2026-06-26T20:35:12.000Z",
            "paidAt": "2026-06-26T20:41:05.000Z"
          }
        },
        {
          "uuid": "7c2b8d11-4e3a-49b0-8f21-0a1b2c3d4e5f",
          "orderId": "WX-1041",
          "address": "TQ5n...wY9k",
          "memo": null,
          "assetCode": "TRX",
          "expectedAmount": "0",
          "status": "check",
          "expiresAt": "2026-06-26T22:00:00.000Z",
          "explorerAddressUrl": "https://tronscan.org/#/address/TQ5n...wY9k",
          "transaction": null
        }
      ],
      "meta": { "page": 1, "perPage": 20, "total": 137 }
    }
  }
  ```
</ResponseExample>

### Поля `meta`

<ResponseField name="page" type="number">Текущая страница.</ResponseField>
<ResponseField name="perPage" type="number">Размер страницы.</ResponseField>
<ResponseField name="total" type="number">Всего записей по всем страницам (для пагинации).</ResponseField>

***

## AML-данные депозита

`GET /v1/public/deposits/{uuid}/aml`

`GET /v1/public/deposits/by-order-id/{orderId}/aml`

Отдельный под-ресурс с результатом AML-скрининга source-of-funds — адреса отправителя
входящей транзакции. Основной объект депозита намеренно не содержит AML-полей; запрашивайте
их явно через эти эндпоинты.

<Note>
  `amlStatus` равен `not_checked`, если AML-скрининг выключен в настройках инстанса, либо
  транзакция ещё не замечена, либо сеть не поддерживается AML-провайдером. Значение
  `checkState: "skipped"` НЕ означает «чисто» — это означает, что проверка не выполнялась.
</Note>

<CodeGroup>
  ```bash cURL theme={null}
  curl https://wallet.your-exchange.com/v1/public/deposits/8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b/aml \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1769990600" \
    -H "X-Signature: 7a2c...44de"
  ```
</CodeGroup>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "8f3a1c2e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
      "orderId": "WX-1042",
      "assetCode": "USDT_TRC20",
      "network": "TRON",
      "senderAddress": "TSenderAddrXyz1234567890abcdefGhJk",
      "amlStatus": "passed",
      "checkState": "success",
      "riskScore": "12.50",
      "riskLevel": "low",
      "decision": "pass",
      "provider": "getblock",
      "topSignal": "exchange",
      "signals": { "exchange": 0.7, "p2p": 0.2 },
      "reportUrl": null,
      "shareUrl": null,
      "checkedAt": "2026-06-26T20:36:00.000Z",
      "manualAction": null,
      "manualActionAt": null,
      "manualActionReason": null
    }
  }
  ```
</ResponseExample>

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

<ResponseField name="uuid" type="string">UUID депозита (тот же, что в `GET /{uuid}`).</ResponseField>
<ResponseField name="orderId" type="string">Ваш `order_id` (label).</ResponseField>
<ResponseField name="assetCode" type="string">Код актива депозита.</ResponseField>
<ResponseField name="network" type="string">Код сети депозита (например `TRON`, `TON`).</ResponseField>

<ResponseField name="senderAddress" type="string | null">
  Адрес отправителя входящей транзакции — именно он проходит AML-скрин. `null`, пока tx не
  замечена.
</ResponseField>

<ResponseField name="amlStatus" type="string">
  Итоговый AML-статус депозита: `not_checked` (не проверялся / AML выключен) | `passed` (чисто)
  \| `flagged` (подозрительно, но не блокировка) | `hold` (заблокирован, ждёт ручного решения)
  \| `rejected` (отклонён).
</ResponseField>

<ResponseField name="checkState" type="string | null">
  Состояние запроса к провайдеру: `pending` | `success` | `failed` | `error` | `skipped`.
  `null`, если проверки не было.
</ResponseField>

<ResponseField name="riskScore" type="string | null">
  Risk-score 0–100 (строка). `null`, если проверки не было.
</ResponseField>

<ResponseField name="riskLevel" type="string | null">
  Уровень риска: `low` | `medium` | `high` | `severe`. Значение `severe` соответствует
  санкциям, терроризму, краденым средствам или эксплуатации — блокировка независимо от score.
</ResponseField>

<ResponseField name="decision" type="string | null">
  Решение скрининга: `pass` | `flag` | `block`.
</ResponseField>

<ResponseField name="provider" type="string | null">Код AML-провайдера.</ResponseField>

<ResponseField name="topSignal" type="string | null">
  Топ-сигнал риска (категория с максимальным весом), например `mixer`, `sanctions`, `scam`,
  `darknet`.
</ResponseField>

<ResponseField name="signals" type="object | null">
  Карта сигналов риска и их весов (0..1). `null`, если провайдер их не вернул.
</ResponseField>

<ResponseField name="reportUrl" type="string | null">Ссылка на полный отчёт провайдера (если есть).</ResponseField>
<ResponseField name="shareUrl" type="string | null">Публичная share-ссылка на отчёт (если есть).</ResponseField>
<ResponseField name="checkedAt" type="string | null">ISO-8601. Когда выполнен AML-скрин. `null`, если проверки не было.</ResponseField>

<ResponseField name="manualAction" type="string | null">
  Ручное действие оператора над заблокированным депозитом: `release` (разрешить свип) |
  `quarantine_now`.
</ResponseField>

<ResponseField name="manualActionAt" type="string | null">ISO-8601. Когда применено ручное действие.</ResponseField>
<ResponseField name="manualActionReason" type="string | null">Причина ручного действия (комментарий оператора).</ResponseField>

***

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

| Код                        | HTTP | Когда возникает                                                        |
| -------------------------- | :--: | ---------------------------------------------------------------------- |
| `VALIDATION_FAILED`        |  400 | тело запроса не прошло валидацию (например, отсутствует `assetCode`)   |
| `INVALID_ASSET`            |  404 | передан неизвестный `assetCode` (сверьтесь с `GET /v1/public/assets`)  |
| `AMOUNT_TOO_MANY_DECIMALS` |  400 | в `expectedAmount` больше знаков после запятой, чем поддерживает актив |
| `INVALID_SIGNATURE`        |  401 | неверная HMAC-подпись — проверьте формулу сообщения                    |
| `TIMESTAMP_SKEW`           |  401 | `X-Timestamp` отличается от серверного более чем на 300 секунд         |
| `IP_NOT_WHITELISTED`       |  403 | IP сервера обменника не в белом списке                                 |
| `LICENSE_REQUIRED`         |  403 | инстанс без активной лицензии — создание депозитов недоступно          |
| `DEPOSIT_NOT_FOUND`        |  404 | депозит не найден или принадлежит другому сайту                        |
| `DUPLICATE_ORDER_ID`       |  409 | `order_id` уже использован (в том числе на другой валюте)              |
| `IDEMPOTENCY_CONFLICT`     |  400 | тот же `X-Idempotency-Key` с другим телом запроса                      |

Полный список кодов и формат конверта ошибки — на странице [Ошибки](/errors).

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

<AccordionGroup>
  <Accordion title="Когда поле transaction перестаёт быть null?">
    Как только платформа замечает первую входящую транзакцию на адрес (и memo) депозита.
    До этого момента `transaction` равен `null`, а `status` остаётся `check`. После детекции
    статус переходит в `process`, а поля транзакции обновляются с каждым подтверждением.
  </Accordion>

  <Accordion title="Как отличить точную оплату от переплаты или недоплаты?">
    По финальному статусу: `paid` — оплачено ровно ожидаемой суммой, `paid_over` — больше,
    `wrong_amount` — меньше. Если `expectedAmount` равен `"0"`, принимается любая сумма и
    исход всегда `paid`. Точную фактическую сумму смотрите в `transaction.receivedAmount`.
    Подробнее — в [Статусах депозита](/deposits/statuses).
  </Accordion>

  <Accordion title="Нужно ли опрашивать API или можно полагаться на webhooks?">
    Рекомендуем основным каналом сделать [webhooks](/webhooks/overview) — платформа сама
    уведомит о смене статуса. GET-эндпоинты используйте как резервный механизм (для
    реконсиляции и при пропущенных вебхуках), опрашивая их с разумным интервалом.
  </Accordion>

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

  <Accordion title="Можно ли получить чужой депозит по uuid?">
    Нет. Все запросы скоупятся по вашему сайту. Запрос депозита, принадлежащего другому сайту,
    вернёт `404 DEPOSIT_NOT_FOUND` — платформа не раскрывает существование чужих UUID.
  </Accordion>
</AccordionGroup>

См. также: [Статусы депозита](/deposits/statuses), [Webhooks](/webhooks/overview),
[Аутентификация](/authentication), [Идемпотентность](/idempotency), [Ошибки](/errors).
