API для разработчиков
Те же проверки, что в кабинете, для ваших программ: AML-аудит адреса, след средств (куда ушли) и источник средств (откуда пришли) в сетях TRON и Ethereum. Платите теми же запросами с того же счёта и по той же цене.
Адрес службы https://api.cifrasled.ru, все методы под /v1. Полное описание методов и полей — в OpenAPI: по нему можно собрать клиента генератором.
Начало работы
- Пополните счёт и включите второй фактор в настройках кабинета. Ключ даёт постоянный доступ к запросам счёта, поэтому без этого его не завести.
- В кабинете, в разделе «API», заведите ключ. Начните с тестового cs_test_…: он не ходит в сеть и ничего не списывает.
- Проверьте, что ключ работает:
curl https://api.cifrasled.ru/v1/key \ -H "Authorization: Bearer $CIFRASLED_KEY"
Запустите аудит адреса. Ответ придёт сразу, со статусом running:
curl https://api.cifrasled.ru/v1/audits \
-H "Authorization: Bearer $CIFRASLED_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: payout-20261021-0042" \
-d '{"address": "T9yD14Nj9j7xAB4dbGeiX9h8unkKLxmGkn"}'
HTTP/1.1 202 Accepted
Location: /v1/checks/6b1f0c2e-…
{"id": "6b1f0c2e-…", "object": "check", "type": "audit",
"status": "running", "progress": [ … ], "queries_spent": 0, … }Заберите результат по номеру проверки. Аудит занимает от нескольких секунд до минуты, след средств — до нескольких минут. Опрашивайте не чаще раза в три секунды или задайте у ключа адрес вебхука.
curl https://api.cifrasled.ru/v1/checks/6b1f0c2e-… \ -H "Authorization: Bearer $CIFRASLED_KEY"
Ключи и защита
Ключ передаётся только заголовком Authorization: Bearer …. Ключ в адресе запроса не принимается: адреса оседают в журналах прокси и в истории браузера.
- cs_live_…
- Боевой ключ: настоящие данные сети, списывает запросы.
- cs_test_…
- Тестовый: подставные ответы, ничего не списывает.
Ключ показывается один раз, при создании. Мы храним только его отпечаток и не можем ни показать ключ снова, ни восстановить. Храните его как пароль: в хранилище секретов, а не в коде и не в репозитории.
- Только с сервера. Ключ в браузере, мобильном приложении или расширении достаётся любому, кто их откроет.
- Права. У ключа отмечено, какие проверки он может запускать: audit, trace, source. Остальное отвечает 403 scope_denied.
- Адреса. Ключу можно разрешить обращаться только с ваших адресов или сетей. С другого адреса ответ — 403 ip_not_allowed.
- Месячный предел. Сколько запросов ключ может потратить за календарный месяц по Москве. Ошибка в цикле не выберет весь счёт.
- Смена ключа. Заведите новый, переключите программу, отзовите старый. Отзыв действует сразу. Проверки, запущенные старым ключом, остаются доступны новому.
- Кто завёл. Ключ работает, пока его создатель управляет счётом. Если владелец уберёт администратора из команды, его ключи перестанут действовать сразу: 401 key_orphaned.
О каждом новом ключе приходит письмо владельцу счёта и тому, кто ключ завёл. Если ключ заводили не вы, отзовите его и смените пароль.
Проверки
- POST /v1/audits
- AML-аудит: можно ли иметь дело с адресом. Право audit.
- POST /v1/traces
- След VASP: куда ушли средства с адреса, до бирж и других точек остановки. Право trace.
- POST /v1/sources
- AML-источник: откуда пришли средства и насколько они чисты. Право source.
Адрес сети определяется по виду: T… из 34 знаков — TRON, 0x… из 42 — Ethereum. Какие сети подключены, видно в GET /v1/key.
След и источник начинаются с конкретного перевода. Укажите его хэш в tx_id: так проверка начнётся ровно с него. Если хэша нет, передайте сумму строкой в amount и актив в asset, а время в incident_at (для следа) или received_at (для источника) поможет выбрать нужный перевод, если на эту сумму их несколько.
curl https://api.cifrasled.ru/v1/traces \
-H "Authorization: Bearer $CIFRASLED_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: case-7781" \
-d '{"address": "T…", "tx_id": "a3f1…64 знака"}'Повтор без двойного списания
Придумайте Idempotency-Key до отправки (8–128 знаков: латиница, цифры, -, _) и при обрыве связи повторяйте запрос с тем же ключом. Вторая проверка не запустится: вернётся прежняя с заголовком Idempotent-Replayed: true. Тот же ключ с другим адресом или другим видом проверки — 409 idempotency_conflict. Без заголовка каждый запрос запускает новую проверку.
Статусы
- running
- Идёт. В progress — план работы: что сделано, что идёт, что впереди.
- done
- Готово. Результат — в поле по виду проверки: audit, trace или source.
- failed
- Не удалась. Причина — в error.message, отложенные запросы вернулись на счёт.
Список проверок, запущенных ключами счёта, — GET /v1/checks, свежие сверху, по 20 (до 100 через limit). Следующая страница — с before, равным created_at последней строки. Проверки, которые сотрудники делали в кабинете, в список не попадают. Документ PDF готовой проверки — GET /v1/checks/{id}/report.pdf.
Результат
У аудита главное — audit.verdict: ответ advice, уровень risk и оценка score от 0 до 100. Каждый вывод обоснован в reasons и markers; пробелы в данных отмечены в coverage и не выдаются за чистоту.
- dangerous
- Иметь дело нельзя: санкции, заморозка эмитентом, мошеннические метки.
- careful
- Есть тревожные признаки: решайте после разбора причин.
- acceptable
- Ограничений и тревожных признаков не найдено.
- no_data
- Проверить не удалось. Это не одобрение.
У следа и источника — точки, где след остановился (endpoints), с причиной reason: exchange (биржа, у неё есть владелец счёта), frozen (заморожено эмитентом), mixer, swap, rest (средства лежат на адресе), no-data, truncated и другие. Доля, судьба которой известна, — в resolved_pct. Суммы — десятичными строками в единицах актива: числом они теряли бы младшие разряды.
Пересказ модели обычным языком — в conclusion. Он объясняет вывод, но не меняет его, и может отсутствовать.
Метки адресов (labels, endpoints[].label) пишут посторонние люди. Показывайте их как текст, а в таблицах экранируйте: значение, начинающееся с =, станет формулой у того, кто откроет файл.
Вебхуки
Если у ключа задан адрес вебхука, по завершении каждой его проверки придёт POST с событием check.completed или check.failed. В теле — та же запись проверки, что отдаёт GET /v1/checks/{id}.
POST /ваш/адрес
Cifrasled-Event: check.completed
Cifrasled-Delivery: 0d9c…
Cifrasled-Signature: t=1761052800,v1=5257a869e7ec…
{"id": "0d9c…", "object": "event", "type": "check.completed",
"livemode": true, "data": {"check": { … }}}Подпись — HMAC-SHA256 секретом вебхука от строки t.тело. Секрет показывается один раз, вместе с ключом. Проверяйте подпись по сырому телу запроса, до разбора JSON, и отвергайте сообщения старше пяти минут:
# Python
import hashlib, hmac, time
def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
ts = int(parts.get("t", "0"))
if abs(time.time() - ts) > tolerance:
return False
expected = hmac.new(secret.encode(), f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts.get("v1", ""))// Node.js
import crypto from "node:crypto";
export function verify(secret, header, rawBody, tolerance = 300) {
const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
const ts = Number(parts.t);
if (!ts || Math.abs(Date.now() / 1000 - ts) > tolerance) return false;
const expected = crypto.createHmac("sha256", secret)
.update(`${ts}.`).update(rawBody).digest("hex");
const got = String(parts.v1 ?? "");
return got.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}- Ответьте 2xx в течение 15 секунд, а тяжёлую обработку ведите после ответа.
- При другом ответе или молчании повторим через 1, 5, 15 минут, час, 3, 6 и 12 часов, а затем перестанем. Результат при этом остаётся доступен по GET /v1/checks/{id}.
- Одно событие может прийти дважды. Различайте их по id события.
- Адрес — только https:// с доступным из интернета именем. Сообщения уходят с адреса 2.58.16.209, перенаправлений не выполняем.
Ошибки
Тело ошибки одинаковое у всех методов. Ветвитесь по code: текст в message написан для человека и может уточняться. request_id присылайте в поддержку вместо ключа.
{"error": {"code": "invalid_address", "param": "address",
"message": "Адрес TRON начинается с T", "request_id": "c41e…"}}| HTTP | code | Что делать |
|---|---|---|
| 400 | invalid_request | Поле в param не годится. Исправьте запрос. |
| 400 | invalid_address | Адрес не той длины, не той сети или с опечаткой. |
| 400 | network_unavailable | Сеть адреса не подключена. Список — в GET /v1/key. |
| 401 | unauthorized | Ключа нет, он неверен или отозван. |
| 401 | key_orphaned | Создатель ключа больше не управляет счётом. Заведите новый. |
| 402 | insufficient_balance | Не хватает запросов. Пополните счёт в кабинете. |
| 402 | key_limit_reached | Ключ выбрал месячный предел. Поднимите его в кабинете. |
| 403 | ip_not_allowed | Адреса обращения нет в списке ключа. |
| 403 | scope_denied | Ключу не разрешён этот вид проверок. |
| 404 | not_found | Нет такой проверки на этом счёте. |
| 409 | idempotency_conflict | Ключ повтора уже занят другой проверкой. |
| 409 | check_not_ready | Документ появится, когда проверка завершится. |
| 429 | rate_limited | Подождите столько секунд, сколько в Retry-After. |
| 429 | concurrency_limited | Дождитесь завершения одной из идущих проверок. |
| 503 | upstream_unavailable | Источник данных сети недоступен. Запросы не списаны. |
| 503 | report_unavailable | Служба печати недоступна. Повторите позже. |
| 500 | internal_error | Наша ошибка. Повторите позже с тем же Idempotency-Key. |
Пределы
- 60 в минуту
- Запросов к API на один ключ. В ответах — заголовок RateLimit-Limit.
- 3 проверки
- Одновременно идущих на один ключ.
- 20 в минуту
- Документов PDF на один ключ.
Сверх предела ответ — 429 с заголовком Retry-After. Если пределов не хватает, напишите на info@cifrasled.ru: поднимем для вашего ключа.
Списание
Цены в запросах — GET /v1/prices, остаток ключа — GET /v1/balance. Аудит стоит фиксированно. След и источник считаются по работе: каждый раскрытый адрес цепочки — запрос, поэтому указана цена самого короткого хода и минимальный остаток для запуска.
При запуске запросы откладываются, по завершении списывается сделанное, остальное возвращается. За неудавшуюся проверку не списывается ничего. Каждое списание видно в журнале счёта в кабинете с пометкой «API».
Тестовый режим
Ключ cs_test_… принимает те же запросы, но не обращается к сети и ничего не списывает. Проверка «идёт» три секунды, затем отдаёт подставной результат. Исход выбирается полем test_scenario:
- /v1/audits
- acceptable, careful, dangerous, failed
- /v1/traces
- traced, failed
- /v1/sources
- clean, tainted, failed
Тестовые проверки хранятся сутки и видны только тестовым ключам, не больше 1000 в сутки на ключ. У них нет документа PDF и вебхуков. В ответах livemode: false. Боевой ключ поле test_scenario отклоняет.
Версии и хранение
Версия — в пути: /v1. Внутри неё могут появляться новые поля и новые значения перечислений, поэтому разбирайте ответ так, чтобы незнакомое не ломало программу. Удалить или переименовать поле, изменить его смысл можно только в новой версии; о ней предупредим письмом владельцам ключей, а /v1 продолжит работать.
Результат проверки хранится семь дней (expires_at), затем удаляется вместе со следами доставки вебхуков. Забирайте результат к себе. Порядок обработки данных — в политике.