> ## 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-скрин: проверка адресов и транзакций

> iEXWallet AML: запуск скрина риска по требованию, опрос результата и список валют через те же API-ключи

iEXWallet AML позволяет вашей CMS скринить криптоадреса и транзакции на риск (санкции, скам,
даркнет, миксеры и т.п.) **через те же ключи API, что и кошелёк** — отдельная интеграция с
AML-провайдером не нужна. Платформа сама выбирает подключённого провайдера и скрывает его внутренние
детали (код провайдера, его идентификаторы проверки, сырой ответ наружу не отдаются).

Этот раздел — про скрин **по требованию**: вы сами передаёте адрес или хэш транзакции и получаете
оценку риска. Если же вам нужен AML-результат уже принятого депозита (скрин адреса отправителя
выполняется платформой автоматически), смотрите [AML по депозиту](/aml/deposit-checks).

<Note>
  AML — лицензируемая возможность. Если она не включена на вашем инстансе, эндпоинты вернут `403`
  с кодом `LICENSE_REQUIRED`. Подключение и настройка AML-провайдера выполняются на стороне оператора
  (Админка → AML → Провайдеры).
</Note>

Аутентификация — та же HMAC-подпись, что и у депозитов/выплат (см. [Аутентификация](/authentication)).
Ответы — в конверте `{ "ok": true, "data": ... }` либо `{ "ok": false, "error": {...} }`. К AML
применяется тот же [per-site rate-limit](/rate-limits), что и к остальному Public API.

## Эндпоинты

| Метод  | Путь                           | Назначение                            |
| ------ | ------------------------------ | ------------------------------------- |
| `GET`  | `/v1/public/aml/currencies`    | какие валюты можно скринить           |
| `POST` | `/v1/public/aml/checks`        | запустить скрин адреса или транзакции |
| `GET`  | `/v1/public/aml/checks/{uuid}` | получить и опросить результат         |

## Синхронный или асинхронный результат

Скрин выполняется через внешнего провайдера и в общем случае **асинхронный**. На `POST` платформа
создаёт проверку и сразу возвращает её текущее состояние:

* если провайдер ещё считает — придёт `status: "pending"`; тогда опрашивайте
  `GET /v1/public/aml/checks/{uuid}`, пока статус не станет терминальным;
* если результат уже готов (или валюта не поддерживается) — `POST` сразу вернёт терминальный
  статус (`success`, `failed`, `error` или `skipped`).

Терминальные статусы: `success`, `failed`, `error`, `skipped`. Риск-оценку (`riskScore`/`riskLevel`)
несёт только `success`. Обычно результат готов за несколько секунд. Подробно про трактовку статусов и
уровней риска — [Уровни риска и статусы](/aml/risk-levels).

<Tip>
  Не опрашивайте `GET /checks/{uuid}` в тугом цикле. Достаточно интервала в несколько секунд:
  запрос на чтение реконсилит `pending`-проверку у провайдера, поэтому слишком частый опрос только
  расходует ваш rate-limit без пользы.
</Tip>

***

## Список доступных валют

```http theme={null}
GET /v1/public/aml/currencies
```

Возвращает allowlist валют подключённого провайдера. Каждый элемент описывает поддерживаемую валюту в
терминах сети и символа провайдера. Пустой список означает, что провайдер ещё не синхронизировал
список валют — скрин при этом всё равно возможен, но неподдерживаемая валюта/сеть вернётся как
`skipped`.

<Note>
  Поле `symbol` здесь — это символ валюты у провайдера (например `USDT`, `TRX`). В теле `POST /checks`
  вы передаёте **код актива платформы** в поле `assetCode` (например `USDT_TRC20`) — см.
  [Справочники активов и сетей](/currencies). Это разные идентификаторы: один описывает валюту у
  AML-провайдера, второй — актив в каталоге кошелька.
</Note>

<RequestExample>
  ```bash cURL theme={null}
  curl https://wallet.your-exchange.com/v1/public/aml/currencies \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1781524800" \
    -H "X-Signature: 9f1c2b3a4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70"
  ```

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

  const BASE_URL = "https://wallet.your-exchange.com";
  const API_ID = "pk_live_a1b2c3d4";
  const API_SECRET = process.env.API_SECRET; // никогда не передаётся по сети

  function signedHeaders(rawBody = "") {
    const ts = Math.floor(Date.now() / 1000).toString();
    const message = `${ts}.${rawBody}`;
    const signature = crypto
      .createHmac("sha256", API_SECRET)
      .update(message)
      .digest("hex");
    return {
      "X-Api-Id": API_ID,
      "X-Timestamp": ts,
      "X-Signature": signature,
    };
  }

  const res = await fetch(`${BASE_URL}/v1/public/aml/currencies`, {
    headers: signedHeaders(), // GET → пустое тело → message = "<ts>."
  });
  const { ok, data } = await res.json();
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "ok": true,
    "data": {
      "items": [
        { "network": "TRON", "symbol": "TRX", "name": "TRON", "contractAddress": null, "isToken": false },
        { "network": "TRON", "symbol": "USDT", "name": "Tether USD", "contractAddress": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t", "isToken": true },
        { "network": "ETHEREUM", "symbol": "USDT", "name": "Tether USD", "contractAddress": "0xdAC17F958D2ee523a2206206994597C13D831ec7", "isToken": true }
      ]
    }
  }
  ```
</ResponseExample>

### Поля валюты

<ResponseField name="network" type="string">Код сети (например `TRON`, `ETHEREUM`).</ResponseField>
<ResponseField name="symbol" type="string">Символ валюты у провайдера (например `USDT`, `TRX`).</ResponseField>
<ResponseField name="name" type="string">Человекочитаемое название валюты.</ResponseField>
<ResponseField name="contractAddress" type="string | null">Адрес контракта токена. `null` — нативная валюта сети.</ResponseField>
<ResponseField name="isToken" type="boolean">`true`, если это токен (есть `contractAddress`), иначе нативная валюта.</ResponseField>

***

## Запустить скрин

```http theme={null}
POST /v1/public/aml/checks
```

Скринит адрес (по умолчанию) или транзакцию через подключённого провайдера. Возвращает созданную
проверку: либо `pending` (опрашивайте по `uuid`), либо сразу терминальный статус.

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

<ParamField body="network" type="string" required>
  Сеть адреса или транзакции. Допустимые значения соответствуют каталогу сетей платформы
  (например `TRON`, `TON`, `ETHEREUM`, `BSC`, `POLYGON`, `BITCOIN`, `LITECOIN`, `XRP`, `SOLANA`).
  Если сеть не поддерживается провайдером — проверка завершится статусом `skipped`.
</ParamField>

<ParamField body="address" type="string" required>
  Адрес для скрина (до 255 символов). Обязателен для `checkMethod` `address` и `both`.
</ParamField>

<ParamField body="assetCode" type="string">
  Код актива платформы (как в [справочнике активов](/currencies)), например `USDT_TRC20`. Если не
  указан — берётся нативная валюта сети. Для токенов влияет на то, какой контракт скринится.
  До 64 символов.
</ParamField>

<ParamField body="txHash" type="string">
  Хэш транзакции (до 255 символов). Нужен для `checkMethod` `transaction` и `both`.
</ParamField>

<ParamField body="checkMethod" type="string">
  Метод скрина: `address`, `transaction` или `both`. По умолчанию — `transaction`, если задан
  `txHash`, иначе `address`.
</ParamField>

<Tip>
  Передавайте заголовок `X-Idempotency-Key` (UUID). Повтор с тем же ключом не потратит лишнюю квоту
  провайдера и вернёт ту же проверку. Идемпотентность скоупится по сайту и кешируется на 1 час.
  См. [Идемпотентность](/idempotency).
</Tip>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://wallet.your-exchange.com/v1/public/aml/checks \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1781524800" \
    -H "X-Signature: 4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c" \
    -H "X-Idempotency-Key: 3a1f9c2e-5d6e-4f70-9a1b-2c3d4e5f6a7b" \
    -H "Content-Type: application/json" \
    -d '{
      "network": "TRON",
      "assetCode": "USDT_TRC20",
      "address": "TKh9xY2bV8cE3fG4hJ5kL6mN7pQ8rS9tU"
    }'
  ```

  ```javascript Node.js theme={null}
  const body = JSON.stringify({
    network: "TRON",
    assetCode: "USDT_TRC20",
    address: "TKh9xY2bV8cE3fG4hJ5kL6mN7pQ8rS9tU",
  });

  const res = await fetch(`${BASE_URL}/v1/public/aml/checks`, {
    method: "POST",
    headers: {
      ...signedHeaders(body), // подпись считается по СЫРОМУ телу
      "Content-Type": "application/json",
      "X-Idempotency-Key": crypto.randomUUID(),
    },
    body,
  });
  const { ok, data } = await res.json();

  // если data.status === "pending" — опросите GET /v1/public/aml/checks/{data.uuid}
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Created theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "0f1c8b2a-5d6e-4f70-9a1b-2c3d4e5f6a7b",
      "status": "success",
      "network": "TRON",
      "assetCode": "USDT_TRC20",
      "address": "TKh9xY2bV8cE3fG4hJ5kL6mN7pQ8rS9tU",
      "txHash": null,
      "checkMethod": "address",
      "riskScore": "12.50",
      "riskLevel": "low",
      "topSignal": "exchange",
      "signals": { "exchange": 0.8, "p2p": 0.1 },
      "reportUrl": "https://provider.example/report/0f1c8b2a",
      "shareUrl": null,
      "reason": null,
      "createdAt": "2026-06-18T12:00:00.000Z",
      "completedAt": "2026-06-18T12:00:03.000Z"
    }
  }
  ```

  ```json 201 Created (pending) theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "0f1c8b2a-5d6e-4f70-9a1b-2c3d4e5f6a7b",
      "status": "pending",
      "network": "TRON",
      "assetCode": "USDT_TRC20",
      "address": "TKh9xY2bV8cE3fG4hJ5kL6mN7pQ8rS9tU",
      "txHash": null,
      "checkMethod": "address",
      "riskScore": null,
      "riskLevel": null,
      "topSignal": null,
      "signals": null,
      "reportUrl": null,
      "shareUrl": null,
      "reason": null,
      "createdAt": "2026-06-18T12:00:00.000Z",
      "completedAt": null
    }
  }
  ```
</ResponseExample>

***

## Получить результат

```http theme={null}
GET /v1/public/aml/checks/{uuid}
```

Возвращает текущее состояние проверки по её `uuid`. Если она ещё `pending` — платформа дёргает
провайдера и реконсилит статус, поэтому именно этим эндпоинтом вы дожидаетесь готового результата.
Структура `data` — та же, что у `POST` выше.

<RequestExample>
  ```bash cURL theme={null}
  curl https://wallet.your-exchange.com/v1/public/aml/checks/0f1c8b2a-5d6e-4f70-9a1b-2c3d4e5f6a7b \
    -H "X-Api-Id: pk_live_a1b2c3d4" \
    -H "X-Timestamp: 1781524860" \
    -H "X-Signature: 819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70819a2b3c4d5e6f70"
  ```
</RequestExample>

<ResponseExample>
  ```json 200 OK theme={null}
  {
    "ok": true,
    "data": {
      "uuid": "0f1c8b2a-5d6e-4f70-9a1b-2c3d4e5f6a7b",
      "status": "success",
      "network": "TRON",
      "assetCode": "USDT_TRC20",
      "address": "TKh9xY2bV8cE3fG4hJ5kL6mN7pQ8rS9tU",
      "txHash": null,
      "checkMethod": "address",
      "riskScore": "12.50",
      "riskLevel": "low",
      "topSignal": "exchange",
      "signals": { "exchange": 0.8, "p2p": 0.1 },
      "reportUrl": "https://provider.example/report/0f1c8b2a",
      "shareUrl": null,
      "reason": null,
      "createdAt": "2026-06-18T12:00:00.000Z",
      "completedAt": "2026-06-18T12:00:03.000Z"
    }
  }
  ```
</ResponseExample>

### Поля проверки

<ResponseField name="uuid" type="string">Публичный идентификатор проверки. По нему опрашивайте результат.</ResponseField>
<ResponseField name="status" type="string">Жизненный цикл проверки: `pending`, `success`, `failed`, `error`, `skipped`. См. [Уровни риска и статусы](/aml/risk-levels).</ResponseField>
<ResponseField name="network" type="string">Сеть, переданная в запросе.</ResponseField>
<ResponseField name="assetCode" type="string">Код актива (явный из запроса либо нативная валюта сети, подставленная платформой).</ResponseField>
<ResponseField name="address" type="string">Проверяемый адрес.</ResponseField>
<ResponseField name="txHash" type="string | null">Хэш транзакции, если передавался, иначе `null`.</ResponseField>
<ResponseField name="checkMethod" type="string">Применённый метод: `address`, `transaction` или `both`.</ResponseField>
<ResponseField name="riskScore" type="string | null">Риск-скор `0`–`100` строкой (например `"12.50"`). `null`, если `status` не `success`.</ResponseField>
<ResponseField name="riskLevel" type="string | null">`low`, `medium`, `high` или `severe`. `null`, если `status` не `success`. См. [Уровни риска](/aml/risk-levels).</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="reason" type="string | null">Причина для статусов `skipped`, `error`, `failed` (например валюта не в allowlist или сбой провайдера). `null` для `success`/`pending`.</ResponseField>
<ResponseField name="createdAt" type="string">Когда проверка создана (ISO-8601).</ResponseField>
<ResponseField name="completedAt" type="string | null">Когда проверка завершена (ISO-8601). `null`, пока `pending`.</ResponseField>

***

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

| HTTP  | `error.code`                           | Когда возникает                                          | Что делать                                       |
| ----- | -------------------------------------- | -------------------------------------------------------- | ------------------------------------------------ |
| `403` | `LICENSE_REQUIRED`                     | AML не лицензирован на инстансе                          | Обратитесь к оператору, чтобы включить фичу AML  |
| `400` | `PROVIDER_UNAVAILABLE`                 | Ни один AML-провайдер не включён в настройках            | Оператор должен подключить и включить провайдера |
| `404` | `NOT_FOUND`                            | Проверки с таким `uuid` нет (или она чужого сайта)       | Проверьте `uuid` из ответа `POST`                |
| `400` | `VALIDATION_FAILED`                    | Невалидное тело (нет `network`/`address`, неверный enum) | Сверьтесь с таблицей полей выше                  |
| `401` | `INVALID_SIGNATURE` / `TIMESTAMP_SKEW` | Подпись не сошлась или часы разъехались (±300с)          | См. [Аутентификация](/authentication)            |
| `403` | `IP_NOT_WHITELISTED`                   | IP сервера не в whitelist                                | Добавьте IP в Админке                            |
| `429` | `RATE_LIMITED`                         | Превышен per-site лимит                                  | См. [Rate limits](/rate-limits)                  |

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

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

<AccordionGroup>
  <Accordion title="Почему пришёл skipped, а не success?">
    `skipped` означает, что валюта или сеть не входит в allowlist подключённого провайдера (или провайдер
    явно объявил их неподдерживаемыми). Это **не** значит «адрес чистый» — оценки риска нет. Причина
    указана в поле `reason`. Проверьте, что валюта присутствует в `GET /v1/public/aml/currencies`.
  </Accordion>

  <Accordion title="В чём разница между этим разделом и AML по депозиту?">
    Здесь вы скрините **произвольный** адрес или транзакцию по своему запросу. AML по депозиту
    (`/aml/deposit-checks`) — это read-only выдача результата скрина, который платформа выполняет
    **автоматически** над адресом отправителя входящей транзакции при приёме депозита.
  </Accordion>

  <Accordion title="Как часто опрашивать pending-проверку?">
    Раз в несколько секунд достаточно. Результат обычно готов за единицы секунд. Каждый `GET` по `uuid`
    реконсилит статус у провайдера, поэтому слишком частый опрос только расходует rate-limit.
  </Accordion>

  <Accordion title="Можно ли скринить токен и нативную валюту одним запросом?">
    Нет, один запрос — одна валюта. Чтобы проскринить адрес как держателя токена, передайте `assetCode`
    токена (например `USDT_TRC20`). Без `assetCode` берётся нативная валюта сети.
  </Accordion>
</AccordionGroup>
