Быстрый старт API

Пять запросов, с которых начинается любая интеграция: адрес, перевод, пачка, мониторинг, PDF.

Перед началом

export AML=https://aml.igorevich.net
export KEY=ваш_ключ   # выдаём в @AML_Igorevich_bot, показывается один раз

Каждый запрос — с заголовком Authorization: Bearer $KEY. В ответе заголовки: X-Request-Id (номер запроса), X-Cost (сколько проверок списано), X-RateLimit-Limit / X-RateLimit-Remaining (лимит в минуту).

Стоимость в проверках: адрес — 1, перевод — 2, глубокая проверка — 5, только списки — бесплатно. Подробнее — в тарифах.

1. Проверить адрес

curl -s $AML/v1/screen \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"address": "TU4tDFRvcKhAZ1jdihojmBWZqvJhQCnJ4F",
       "direction": "incoming",
       "context": {"intent": "deposit", "amount_usd": 1500}}'

Сеть по умолчанию — TRON. Для Ethereum или BSC добавьте "chain": "ethereum" или "chain": "bsc" (в этих сетях — USDT и USDC).

ПолеСмысл
decision.actionaccept / accept_and_flag / review / reject / hold — решение по вашей политике
decision.ruleкакое правило сработало, например DIRECT_LISTING или порог по категории
score, bandскор 3–100 и уровень
direct_hits[]адрес сам в списке: какой список, designated_at и published_at, сила попадания
by_category[]доли средств по категориям риска
exposure.unattributed_shareдоля, происхождение которой не установлено (это не риск)
score_upperкаким был бы скор, если бы всё непрослеженное оказалось худшей из сработавших категорий
evidence.stateok / no_history / unavailable …
statussuccess; degraded — сбой источника данных, скор не ниже 75; skipped — сумма ниже порога
verdict_idномер записи в журнале — для PDF и спора

Тестовый адрес выше — Aeza Group (OFAC SDN с 01.07.2025, заморожен Tether): ожидаем score: 100 и reject.

2. Проверить конкретный перевод (FIFO)

curl -s $AML/v1/screen \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"subject": {"type": "transaction",
                   "hash": "<хэш транзакции>",
                   "id": "<адрес клиента в этом переводе>",
                   "direction": "incoming"},
       "method": "fifo",
       "min_amount_usd": 50,
       "context": {"amount_usd": 1500}}'

Считается не весь кошелёк, а сумма этого перевода: какие входы отправителя его оплатили. direction: incoming — клиент прислал вам, outgoing — вы отправили клиенту. Кроме fifo, есть haircut (пропорционально) и auto.

  • Перевода нет — 422 с tx_not_found, leg_not_found или direction_mismatch. Не «риск 0».
  • Сумма ниже min_amount_usd — status: skipped, проверка не списывается.

3. Пачка

До 100 проверок за запрос; ошибка одной строки не роняет остальные:

curl -s $AML/v1/screen/batch \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"items": [
        {"address": "TU4tDFRvcKhAZ1jdihojmBWZqvJhQCnJ4F"},
        {"address": "<адрес 2>", "direction": "outgoing"},
        {"chain": "ethereum", "address": "0x<адрес 3>"}
      ]}'

Только санкционные и чёрные списки, до 1 000 адресов за запрос, бесплатно — для ежедневной сверки базы клиентов:

curl -s $AML/v1/lists/batch \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"addresses": ["TU4tDFRvcKhAZ1jdihojmBWZqvJhQCnJ4F", "<адрес 2>"]}'

4. Поставить адрес на мониторинг

curl -s $AML/v1/monitor \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"chain": "tron",
       "address": "<адрес клиента>",
       "webhook_url": "https://ваш-сайт/aml-hook",
       "events": ["listed", "band", "decision"],
       "interval_hours": 24,
       "ttl_days": 90,
       "customer_ref": "order-18342"}'
  • Сети: tron, bsc, ethereum.
  • Списки сверяются при каждом обновлении (раз в 2 часа), полная перепроверка — раз в interval_hours (не чаще раза в 6 часов).
  • События: listed — попал в список, band — сменился уровень, decision — сменилось решение, category — появилась новая категория.
  • В ответе один раз приходит webhook_secret — сохраните его.
  • Пачкой — POST /v1/monitor/batch, до 1 000 адресов.

Проверка подписи вебхука (Python):

import hmac, hashlib

def valid(secret: str, headers: dict, body: bytes) -> bool:
    ts = headers["X-AML-Timestamp"]
    expected = "sha256=" + hmac.new(secret.encode(), f"{ts}.".encode() + body,
                                    hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, headers["X-AML-Signature"])

Не ответили 2xx — повторим через 1 мин, 5 мин, 30 мин, 2 ч, 12 ч. Проверить доставку — POST /v1/webhooks/test, журнал доставок — GET /v1/webhooks/deliveries.

5. PDF-заключение

curl -s -D - -o aml-report.pdf \
  "$AML/v1/verdicts/<verdict_id>/report.pdf?view=public" \
  -H "Authorization: Bearer $KEY"
  • view=public — для клиента и мониторинга: факты из списков с датами и ссылками отдельно от расчётов, без ваших порогов и поведенческих признаков.
  • view=internal — полная версия для вас.
  • Заголовок X-Report-Sha256 — отпечаток файла; сохраните рядом с PDF. В подвале каждой страницы — хэш записи журнала.
  • Те же данные в JSON: /v1/verdicts/<verdict_id>/report.json.

Публичная ссылка без ключа

curl -s -X POST $AML/v1/verdicts/<verdict_id>/share \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"ttl_days": 30}'

В ответе — public_url вида https://aml.igorevich.net/r/<токен> и срок действия. По ссылке открывается только публичная версия PDF (/r/<токен>.json — её данные); истёкшая ссылка отдаёт 404.


Полезное

ЗапросЗачем
GET /v1/policiesкакие политики доступны и что в них
GET /v1/categories?compat=amlbotсправочник 42 категорий и соответствие ключам AMLBot
GET /v1/lists/<адрес>/historyкогда адрес попадал в списки и выходил из них
GET /v1/journal/verifyцела ли цепочка хэшей журнала
GET /healthzсвежесть списков и отставание базы от сети — отличить «сломалось у нас» от «у вас»
GET /methodologyметодика расчёта, на которую ссылается PDF

Коды ошибок: 401 — ключ неверен; 422 — адрес невалиден или перевод не найден; 429 — превышен лимит (смотрите Retry-After); 503 — не уложились в 15 секунд или недоступен источник (смотрите Retry-After). Ответа 200 со скором 0 не бывает никогда.

Подключаете обменный скрипт, а не свой код? Смотрите Premium Exchanger и iEXExchanger.