ChainZap Документация API
RU
Получить доступ к API
Разделы
Получить доступ к API

Поиск работает в браузере. Выберите результат клавишами ↑ ↓ и откройте его клавишей Enter.

ChainZap / Документация

API проверки транзакций

Проверьте транзакцию перед зачислением платежа. Здесь описаны подключение API, проверка переводов в TRON и обработка результатов.

Проверка транзакции перед зачислением

ChainZap помогает понять, что произошло с транзакцией и достаточно ли полученных данных для вашего платёжного процесса. API возвращает данные перевода, оценку риска и, при необходимости, сравнение с реквизитами платежа.

Что поддерживается

В версии v1 поддерживается TRON. Ethereum и TON находятся в планах; запросы с этими сетями API пока не принимает. Доступ предоставляется по приглашению, с лимитами для вашей организации.

  • POST /v1/transaction/check: проверить транзакцию по хешу.
  • GET /v1/usage: посмотреть лимиты и статистику запросов.

Отправляйте запросы со своего сервера, передавая ключ в заголовке X-API-Key.

Как читать ответ

HTTP 200 означает, что запрос обработан. Сам по себе этот код не подтверждает получение платежа или отсутствие риска.

Проверяйте вместе transaction_state, overall_state, coverage, результаты сравнения платежа, freshness и reasons. Значение null может означать, что данных нет или что вы не запрашивали соответствующее сравнение. Отсутствие данных нельзя считать успешной проверкой.

Начните с первого запроса, затем изучите полноту данных и правила повторных запросов.

Отправьте первый запрос

Получите доступ

Напишите в поддержку ChainZap, чтобы согласовать подключение и получить приглашение. После входа в кабинет откройте API-ключи, создайте ключ с понятным названием и сохраните его в защищённом хранилище на сервере. Полный ключ показывается один раз.

Проверьте транзакцию по хешу

В примере ниже используются вымышленный ключ и хеш. Замените их своими значениями на сервере. Сохраните Idempotency-Key вместе с данными операции до отправки: он понадобится, если запрос придётся повторить.

cURL
curl --include --max-time 15 'https://api.chainzap.io/v1/transaction/check' \
  -H 'Content-Type: application/json' \
  -H 'X-API-Key: cz_live_000000000000.fictional_example_only' \
  -H 'Idempotency-Key: merchant-order-1001-check-1' \
  -H 'X-Request-ID: merchant-order-1001-attempt-1' \
  --data '{"network":"tron","tx_hash":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}'

Сохраните X-Request-ID из заголовков ответа. Он совпадает с request_id в JSON и помогает поддержке найти запрос. Для вымышленного хеша возможен результат not_found; подробнее о нём написано в статусах транзакции.

Сравните перевод с данными платежа

Добавьте нужного получателя, контракт токена и сумму, если вам важно проверить не только транзакцию, но и её соответствие конкретному платежу.

JSON
{
  "network": "tron",
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "expected_recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "expected_token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "expected_amount": "1250.000001"
}

Адреса здесь приведены только для примера, отправлять на них средства не нужно. Токен определяется по контракту, а сумма передаётся строкой с точкой. Результаты трёх сравнений относятся к одному выбранному переводу. Подробнее: сравнение платежа.

Если ответ не пришёл

Повторите запрос с тем же телом и тем же Idempotency-Key. Не создавайте новый ключ только из-за обрыва соединения: первый запрос мог успеть выполниться.

Если ответ с ошибкой получен, повторяйте запрос только при error.retryable=true, учитывайте Retry-After и ограничивайте число попыток. Сохранённая ошибка может вернуться повторно без нового обращения к источникам данных.

Готовые алгоритмы приведены в примерах Python и TypeScript. Проверить остаток лимита можно через статистику запросов.

Доступ и API-ключи

Передавайте ключ только с сервера

Добавляйте X-API-Key в каждый запрос к рабочему API и используйте HTTPS. Не помещайте ключ в URL, код сайта, хранилище браузера, аналитику, Git или сообщение в поддержку.

Ключ даёт доступ к одной организации. Указать другую организацию в теле запроса нельзя. Вход в кабинет и авторизация по API-ключу работают независимо друг от друга.

Участники с ролями owner, admin и developer могут создавать, заменять и отзывать ключи. Роли billing и viewer позволяют просматривать статистику и сведения о ключах, но не управлять ключами и не запускать проверки.

Создание, замена и отзыв

Создавайте отдельный ключ с понятным названием для каждой интеграции. Полное значение видно только при создании или замене. В списке отображается начало ключа.

При замене старый ключ сразу отзывается, а новый создаётся в той же операции. После этого обновите настройки на сервере. Для планового перехода без перерыва сначала создайте отдельный ключ, переведите приложение на него и проверьте подключение. Затем отзовите прежний.

Ошибки доступа

  • 401 invalid_api_key: ключ неверен или отозван.
  • 403 tenant_suspended: доступ организации приостановлен.
  • 403 network_not_enabled: выбранная сеть не включена для организации.

Сначала устраните причину. Повторение того же запроса без изменения доступа не поможет.

Проверка одной транзакции

POST /v1/transaction/check

Отправьте JSON с обязательными полями network и tx_hash. Неизвестные поля отклоняются.

Поле Что передать
network Только "tron".
tx_hash Хеш транзакции: 64 шестнадцатеричных символа.
expected_recipient Необязательно: адрес получателя платежа в TRON.
expected_token_contract Необязательно: адрес контракта нужного токена в TRON.
expected_amount Необязательно: сумма строкой, например "10.25".

Адреса проверяются с учётом контрольной суммы TRON. Сумма должна быть неотрицательной; JSON-числа и запись через e не принимаются. Размер тела запроса ограничен 4 КиБ.

Передайте Content-Type: application/json, серверный X-API-Key и Idempotency-Key для безопасного повтора. Заголовок X-Request-ID позволяет связать запрос с вашим журналом операций. Полный перечень типов и полей находится в справочнике API.

Что приходит в ответе

Ответ содержит статус транзакции, число подтверждений, переводы, выбранный перевод, риск, результат санкционной проверки, подлинность токена, сравнение с платежом, полноту и актуальность данных. В reasons возвращаются от 2 до 5 наиболее важных пояснений.

Читайте transaction_state отдельно от overall_state. Обрабатывайте null явно. Суммы переводов и доли риска представлены строками.

transfers_truncated=true означает, что список переводов сокращён. AMBIGUOUS_TRANSFER означает, что требованиям соответствуют несколько переводов. Оба случая требуют внимания. Нельзя считать сокращённый список полным или объединять результаты сравнения разных переводов.

Как учитывается проверка

Проверка с полными данными расходует одну единицу месячного лимита, даже если найден высокий риск. За неполные данные проверка не списывается. Повтор уже выполненной операции с тем же ключом не списывает лимит второй раз.

Сравните перевод с данными платежа

Если нужно проверить конкретный платёж, передайте адрес получателя, контракт токена и сумму в полях expected_*. Можно передать все три поля или только нужные.

Все сравнения относятся к одному переводу

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

Поля recipient_match, token_match и amount_match относятся именно к этому выбранному переводу. Если полных совпадений несколько, в ответе появляется AMBIGUOUS_TRANSFER.

Результат Значение
true Значение совпало с указанным вами.
false Значение удалось проверить, но оно не совпало.
null Сравнение не запрашивалось или для него недостаточно данных.

Что именно сравнивается

Если вы передали ожидаемое значение, но данных для сравнения не хватает, соответствующее поле содержит null, покрытие — partial, а среди причин появляется EXPECTED_DATA_UNAVAILABLE. Например, без количества десятичных знаков токена нельзя утверждать, что сумма не совпала. Не считайте null подтверждением совпадения.

Получатель проверяется по адресу TRON с корректной контрольной суммой. Токен сравнивается по адресу контракта, а не по названию или символу: одинаковый символ не доказывает, что это один и тот же токен.

Сумма передаётся десятичной строкой, например "10.000001". Сервис переводит её в целые минимальные единицы токена и сравнивает точно, без допуска округления. Если указанная точность несовместима с количеством знаков токена, API возвращает 422 invalid_expected_amount.

Пример несовпадения

Вы ожидаете "10.000001", а в выбранном переводе указано "10". Результат: amount_match=false и причина EXPECTED_AMOUNT_MISMATCH.

Для несовпадения получателя используется EXPECTED_RECIPIENT_MISMATCH, для другого контракта токена: EXPECTED_TOKEN_MISMATCH. Совпадение суммы само по себе не подтверждает совпадение получателя и токена. Перед зачислением платежа проверьте все нужные сравнения, статус транзакции и общую оценку.

Лимиты и статистика запросов

GET /v1/usage

Запрос возвращает лимиты и статистику организации, которой принадлежит API-ключ.

cURL
curl --include --max-time 15 'https://api.chainzap.io/v1/usage?days=30' \
  -H 'X-API-Key: cz_live_000000000000.fictional_example_only' \
  -H 'X-Request-ID: merchant-usage-1001'

Параметр days задаёт период статистики от 1 до 90 дней. По умолчанию используется 30. Idempotency-Key для этого запроса не нужен. Чтение статистики учитывается в лимите частоты запросов, но не расходует лимит проверок транзакций.

Остаток на текущий месяц

period.start и period.end обозначают границы календарного месяца по UTC.

Поле Значение
limit Доступное число проверок за месяц.
used Уже учтённые проверки с полными данными.
reserved Места в лимите, занятые текущими запросами.
remaining Остаток: max(0, limit - used - reserved).

Если запрос завершается без списания, занятое им место освобождается. Лимит общий для всех ключей организации и запросов из кабинета.

Статистика за выбранный период

В recent учитываются завершённые проверки за последние days дней. Повторная выдача сохранённого ответа не создаёт новую проверку. Статистика содержит число запросов, списанных проверок, ошибок и результатов LIMITED_DATA, среднее время ответа и распределение по сетям и общей оценке.

Хеши транзакций и ответы источников данных в статистику не входят. В кабинете дополнительно доступны показатели по дням UTC и p50/p95, если за последние 30 дней накопилось не менее 20 завершённых проверок. Успешные HTTP-ответы могут содержать неполные данные: это часть общего числа ответов, а не отдельная прибавка к нему.

Примеры интеграции

Python: запрос с ограниченными повторами

Пример использует httpx и выполняется на сервере. API-ключ вымышленный. В рабочей интеграции загружайте ключ из защищённого хранилища, а operation_key и body сохраняйте в своём журнале операций до первой попытки.

Python
import random
import time
import httpx

api_key = "cz_live_000000000000.fictional_example_only"
operation_key = "merchant-order-1001-check-1"
body = {"network": "tron", "tx_hash": "a" * 64}


def check():
    with httpx.Client(timeout=15, follow_redirects=False) as client:
        for attempt in range(4):
            try:
                response = client.post(
                    "https://api.chainzap.io/v1/transaction/check",
                    headers={
                        "X-API-Key": api_key,
                        "Idempotency-Key": operation_key,
                        "X-Request-ID": f"order-1001-attempt-{attempt + 1}",
                    },
                    json=body,
                )
            except httpx.TransportError:
                if attempt == 3:
                    raise RuntimeError("unresolved_transport_outcome") from None
                time.sleep(2 ** attempt + random.uniform(0, 1))
                continue
            print("X-Request-ID:", response.headers.get("X-Request-ID"))
            try:
                result = response.json()
            except ValueError:
                raise RuntimeError("unresolved_gateway_response") from None
            if response.is_success:
                return result
            error = result.get("error", {})
            if error.get("retryable") is not True:
                raise RuntimeError(error.get("code", "unresolved_response"))
            if response.headers.get("Idempotent-Replayed") == "true":
                raise RuntimeError("stored_error_requires_reconciliation")
            try:
                instructed = int(response.headers.get("Retry-After", "0"))
            except ValueError:
                raise RuntimeError("invalid_retry_after") from None
            delay = max(instructed, 2 ** attempt) + random.uniform(0, 1)
            if attempt == 3 or delay > 30:
                raise RuntimeError("schedule_retry_with_same_operation_key")
            time.sleep(delay)

После перезапуска используйте прежние данные операции. Алгоритм учитывает сетевые ошибки и ответы с разрешённым повтором, не создавая каждый раз новую проверку. Обрабатывайте результат в соответствии с правилами своего платёжного процесса. Не записывайте в лог body или полный ответ.

TypeScript: запрос с сервера

Этот код предназначен для сервера. Не помещайте настоящий ключ в браузер. Сохраните ключ операции и тело до вызова функции, как в примере Python.

TypeScript
type PublicResult = {
  request_id?: string;
  error?: { code: string; message: string; retryable: boolean };
  [field: string]: unknown;
};

const apiKey = "cz_live_000000000000.fictional_example_only";
const operationKey = "merchant-order-1001-check-1";
const body = { network: "tron", tx_hash: "a".repeat(64) };
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

async function check(): Promise<PublicResult> {
  for (let attempt = 0; attempt < 4; attempt++) {
    let response: Response;
    try {
      response = await fetch("https://api.chainzap.io/v1/transaction/check", {
        method: "POST", redirect: "error", signal: AbortSignal.timeout(15000),
        headers: {
          "Content-Type": "application/json", "X-API-Key": apiKey,
          "Idempotency-Key": operationKey,
          "X-Request-ID": `order-1001-attempt-${attempt + 1}`,
        },
        body: JSON.stringify(body),
      });
    } catch {
      if (attempt === 3) throw new Error("unresolved_transport_outcome");
      await wait((2 ** attempt + Math.random()) * 1000);
      continue;
    }
    console.info("X-Request-ID:", response.headers.get("X-Request-ID"));
    const result = await response.json() as PublicResult;
    if (response.ok) return result;
    if (result.error?.retryable !== true) {
      throw new Error(result.error?.code ?? "unresolved_response");
    }
    if (response.headers.get("Idempotent-Replayed") === "true") {
      throw new Error("stored_error_requires_reconciliation");
    }
    const instructed = Number(response.headers.get("Retry-After") ?? "0");
    if (!Number.isFinite(instructed) || instructed < 0) {
      throw new Error("invalid_retry_after");
    }
    const delay = Math.max(instructed, 2 ** attempt) + Math.random();
    if (attempt === 3 || delay > 30) {
      throw new Error("schedule_retry_with_same_operation_key");
    }
    await wait(delay * 1000);
  }
  throw new Error("retry_budget_exhausted");
}

Примеры ответов

Ниже приведены подготовленные примеры структуры ответа. Это не результаты реальных проверок. В каждом случае заголовок X-Request-ID равен полю request_id.

Проверяйте не только общую оценку, но и coverage, значения null и пояснения в reasons.

Транзакция подтверждена

Показать полный ответ JSON
JSON
{
  "aml_risk_level": "low",
  "amount": "1250.000001",
  "amount_match": true,
  "confirmations": 27,
  "coverage": "complete",
  "decimals": 6,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "CLEAR",
  "reasons": [
    {
      "category": "transaction",
      "code": "TX_FINALIZED",
      "severity": "info"
    },
    {
      "category": "risk",
      "code": "AML_LOW",
      "severity": "info"
    }
  ],
  "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "recipient_match": true,
  "request_id": "example-confirmed",
  "required_confirmations": 19,
  "sanctions_hit": false,
  "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "token_authenticity": "official",
  "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "token_match": true,
  "token_symbol": "USDT",
  "transaction_category": "trc20_transfer",
  "transaction_state": "confirmed",
  "transaction_type": "TriggerSmartContract",
  "transfers": [
    {
      "amount": "1250.000001",
      "asset_type": "trc20",
      "decimals": 6,
      "index": 0,
      "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "token_id": null,
      "token_symbol": "USDT"
    }
  ],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Ожидание подтверждения

Показать полный ответ JSON
JSON
{
  "aml_risk_level": "low",
  "amount": "1250.000001",
  "amount_match": true,
  "confirmations": 3,
  "coverage": "complete",
  "decimals": 6,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "REVIEW",
  "reasons": [
    {
      "code": "TX_PENDING_CONFIRMATIONS",
      "category": "transaction",
      "severity": "warning"
    },
    {
      "code": "AML_LOW",
      "category": "risk",
      "severity": "info"
    }
  ],
  "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "recipient_match": true,
  "request_id": "example-pending",
  "required_confirmations": 19,
  "sanctions_hit": false,
  "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "token_authenticity": "official",
  "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "token_match": true,
  "token_symbol": "USDT",
  "transaction_category": "trc20_transfer",
  "transaction_state": "pending",
  "transaction_type": "TriggerSmartContract",
  "transfers": [
    {
      "amount": "1250.000001",
      "asset_type": "trc20",
      "decimals": 6,
      "index": 0,
      "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "token_id": null,
      "token_symbol": "USDT"
    }
  ],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Транзакция завершилась ошибкой

Показать полный ответ JSON
JSON
{
  "aml_risk_level": "low",
  "amount": null,
  "amount_match": null,
  "confirmations": 27,
  "coverage": "complete",
  "decimals": 6,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "REVIEW",
  "reasons": [
    {
      "code": "TX_REVERTED",
      "category": "transaction",
      "severity": "warning"
    },
    {
      "code": "TX_FACTS_VERIFIED",
      "category": "transaction",
      "severity": "info"
    }
  ],
  "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "recipient_match": null,
  "request_id": "example-failed",
  "required_confirmations": 19,
  "sanctions_hit": false,
  "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "token_authenticity": "official",
  "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "token_match": null,
  "token_symbol": "USDT",
  "transaction_category": "trc20_transfer",
  "transaction_state": "failed",
  "transaction_type": "TriggerSmartContract",
  "transfers": [],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Транзакция не найдена

JSON
{
  "aml_risk_level": "unknown",
  "amount": null,
  "amount_match": null,
  "confirmations": null,
  "coverage": "complete",
  "decimals": null,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "REVIEW",
  "reasons": [
    {
      "code": "TX_NOT_FOUND",
      "category": "transaction",
      "severity": "warning"
    },
    {
      "code": "TX_FACTS_VERIFIED",
      "category": "transaction",
      "severity": "info"
    }
  ],
  "recipient": null,
  "recipient_match": null,
  "request_id": "example-not-found",
  "required_confirmations": 19,
  "sanctions_hit": null,
  "sender": null,
  "token_authenticity": "unknown",
  "token_contract": null,
  "token_match": null,
  "token_symbol": null,
  "transaction_category": "unknown",
  "transaction_state": "not_found",
  "transaction_type": "unknown",
  "transfers": [],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Недостаточно данных

Показать полный ответ JSON
JSON
{
  "aml_risk_level": "unknown",
  "amount": "1250.000001",
  "amount_match": true,
  "confirmations": 27,
  "coverage": "partial",
  "decimals": 6,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "LIMITED_DATA",
  "reasons": [
    {
      "code": "AML_UNAVAILABLE",
      "category": "risk",
      "severity": "warning"
    },
    {
      "code": "SANCTIONS_UNAVAILABLE",
      "category": "sanctions",
      "severity": "warning"
    }
  ],
  "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "recipient_match": true,
  "request_id": "example-limited-data",
  "required_confirmations": 19,
  "sanctions_hit": null,
  "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "token_authenticity": "official",
  "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "token_match": true,
  "token_symbol": "USDT",
  "transaction_category": "trc20_transfer",
  "transaction_state": "confirmed",
  "transaction_type": "TriggerSmartContract",
  "transfers": [
    {
      "amount": "1250.000001",
      "asset_type": "trc20",
      "decimals": 6,
      "index": 0,
      "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "token_id": null,
      "token_symbol": "USDT"
    }
  ],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Совпадение с санкционным списком

Показать полный ответ JSON
JSON
{
  "aml_risk_level": "low",
  "amount": "1250.000001",
  "amount_match": true,
  "confirmations": 27,
  "coverage": "complete",
  "decimals": 6,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "HIGH_RISK",
  "reasons": [
    {
      "code": "SANCTIONS_HIT",
      "category": "sanctions",
      "severity": "critical"
    },
    {
      "code": "TX_FINALIZED",
      "category": "transaction",
      "severity": "info"
    }
  ],
  "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "recipient_match": true,
  "request_id": "example-sanctions-hit",
  "required_confirmations": 19,
  "sanctions_hit": true,
  "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "token_authenticity": "official",
  "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "token_match": true,
  "token_symbol": "USDT",
  "transaction_category": "trc20_transfer",
  "transaction_state": "confirmed",
  "transaction_type": "TriggerSmartContract",
  "transfers": [
    {
      "amount": "1250.000001",
      "asset_type": "trc20",
      "decimals": 6,
      "index": 0,
      "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "token_id": null,
      "token_symbol": "USDT"
    }
  ],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Данные платежа не совпали

Показать полный ответ JSON
JSON
{
  "aml_risk_level": "low",
  "amount": "1250.000001",
  "amount_match": false,
  "confirmations": 27,
  "coverage": "complete",
  "decimals": 6,
  "freshness": {
    "checked_at": "2026-09-03T12:00:00Z",
    "max_source_age_seconds": 4,
    "risk_data_at": "2026-09-03T12:00:00Z",
    "token_data_at": "2026-09-03T12:00:00Z",
    "transaction_at": "2026-09-03T11:59:00Z"
  },
  "key_exposure": [],
  "network": "tron",
  "overall_state": "REVIEW",
  "reasons": [
    {
      "code": "EXPECTED_AMOUNT_MISMATCH",
      "category": "expected",
      "severity": "warning"
    },
    {
      "code": "TX_FINALIZED",
      "category": "transaction",
      "severity": "info"
    }
  ],
  "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "recipient_match": true,
  "request_id": "example-expected-mismatch",
  "required_confirmations": 19,
  "sanctions_hit": false,
  "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
  "token_authenticity": "official",
  "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
  "token_match": true,
  "token_symbol": "USDT",
  "transaction_category": "trc20_transfer",
  "transaction_state": "confirmed",
  "transaction_type": "TriggerSmartContract",
  "transfers": [
    {
      "amount": "1250.000001",
      "asset_type": "trc20",
      "decimals": 6,
      "index": 0,
      "recipient": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "sender": "TJRabPrwbZy45sbavfcjinPJC18kjpRTv8",
      "token_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
      "token_id": null,
      "token_symbol": "USDT"
    }
  ],
  "transfers_truncated": false,
  "tx_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}

Статус транзакции

Поле transaction_state описывает состояние транзакции в блокчейне. Оно не заменяет оценку риска и проверку полноты данных.

Значение Что означает Как обработать
confirmed Источники подтверждают транзакцию. Проверьте число подтверждений, общую оценку и полноту данных.
pending Транзакция найдена, но окончательное подтверждение ещё не получено. Не считайте расчёт завершённым. После обработки текущего ответа запланируйте отдельную проверку позже.
failed Выполнение завершилось ошибкой или было отменено. Не считайте ожидаемый перевод полученным.
not_found Транзакция не найдена в доступных данных. Проверьте сеть и хеш. Отсутствие записи не подтверждает платёж.
unknown По имеющимся данным статус установить не удалось. Обработайте результат как недостаток данных.

Подтверждения TRON

В v1 требуется 19 подтверждений вместе с данными об окончательном подтверждении сети. Сравнивайте confirmations с required_confirmations. Один только статус confirmed не подтверждает, что остальные проверки завершены.

Разные ситуации показаны в примерах ответов.

Общая оценка

Поле overall_state объединяет результаты проверки транзакции, риска, санкций, токена и реквизитов платежа.

Значение Как понимать
CLEAR Обязательные проверки завершены, проблем не выявлено, требования к подтверждению выполнены. Это не гарантия отсутствия будущего риска.
REVIEW Результат требует внимания: например, подтверждений пока мало, транзакция не выполнена, риск повышен или данные платежа не совпали.
HIGH_RISK Найден высокий или критический риск: например, совпадение с санкционным списком, высокий AML-риск или поддельный токен.
LIMITED_DATA Данные неполные, не поддерживаются или противоречат друг другу. Нельзя обрабатывать как CLEAR.

Проверяйте оценку вместе с данными

Общая оценка и coverage описывают разные свойства ответа. Например, уже обнаруженный высокий риск может сочетаться с неполными данными. При противоречивых сведениях о самой транзакции приоритет получает LIMITED_DATA.

Сохраняйте и анализируйте полученные reasons. Сервис возвращает ограниченный список наиболее важных пояснений, а не полный отчёт по каждому источнику.

Полнота и актуальность данных

Полные и неполные данные

coverage="complete" означает, что данных достаточно для обязательных проверок этого ответа. Это не означает, что транзакция безопасна: проверка может выявить высокий риск.

coverage="partial" означает, что часть обязательных данных отсутствует, не поддерживается или не согласуется между источниками. Причина может относиться к транзакции, активу, токену или оценке риска.

  • Нет результата санкционной проверки: sanctions_hit=null, а не false.
  • Риск не определён: aml_risk_level="unknown".
  • Подлинность токена не установлена: token_authenticity="unknown". Символ токена не доказывает его подлинность.

LIMITED_DATA может возвращаться с HTTP 200. Это полноценный ответ о недостатке данных, а не обязательно ошибка соединения.

Актуальность

Проверяйте freshness.checked_at, время данных отдельных источников и max_source_age_seconds. Если время источника равно null, оно неизвестно.

Повторная выдача по тому же Idempotency-Key возвращает исходный результат с прежним временем и идентификатором запроса. Она не обновляет данные. Если после обработки этого результата нужна более поздняя оценка, создайте отдельную операцию проверки.

Учёт в лимите

Лимит расходуют только проверки с полными данными. Неполные данные, ошибки передачи и повторная выдача сохранённого ответа не списывают дополнительную проверку. Для запросов из кабинета действуют те же правила.

Пояснения к результату

Каждый элемент reasons содержит code, category и severity. Уровни важности: info, warning, high, critical. API возвращает от 2 до 5 наиболее важных пояснений.

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

Код Значение
TX_FACTS_VERIFIED Данные транзакции прошли обязательную проверку.
TX_FACTS_PARTIAL Часть необходимых данных транзакции отсутствует.
TX_FACTS_DISAGREE Источники противоречат друг другу.
TX_FINALIZED Требования к окончательному подтверждению выполнены.
TX_PENDING_CONFIRMATIONS Подтверждений пока недостаточно.
TX_REVERTED Транзакция завершилась ошибкой.
TX_NOT_FOUND Транзакция не найдена.
TRANSFERS_TRUNCATED Список переводов сокращён.
AMBIGUOUS_TRANSFER Условиям платежа соответствуют несколько переводов.
AML_UNSUPPORTED_ASSET Для актива не поддерживается нужная AML-проверка.
AML_UNAVAILABLE Нужные данные для оценки AML-риска недоступны.
AML_LOW По доступной оценке AML-риск низкий.
AML_ELEVATED По доступной оценке AML-риск повышен.
AML_HIGH По доступной оценке AML-риск высокий или критический.
SANCTIONS_HIT Есть совпадение с санкционным списком.
SANCTIONS_CLEAR Доступная санкционная проверка не выявила совпадений.
SANCTIONS_UNAVAILABLE Санкционная проверка недоступна. Это не отсутствие совпадений.
TOKEN_AUTH_UNAVAILABLE Данные для проверки подлинности токена недоступны.
TOKEN_OFFICIAL Контракт распознан как официальный.
TOKEN_FAKE Токен определён как поддельный.
TOKEN_UNKNOWN Подлинность токена не установлена.
EXPECTED_RECIPIENT_MISMATCH Получатель выбранного перевода не совпал с указанным.
EXPECTED_TOKEN_MISMATCH Контракт выбранного токена не совпал с указанным.
EXPECTED_AMOUNT_MISMATCH Сумма выбранного перевода не совпала с указанной.
EXPECTED_DATA_UNAVAILABLE Для запрошенного сравнения не хватает данных о переводе. Соответствующее поле сравнения содержит null.

Повтор запроса без двойного списания

Idempotency-Key связывает попытки отправки с одной проверкой. Это ключ операции, а не API-ключ для доступа.

Сохраните ключ до первого запроса

Допустимо от 1 до 128 печатных ASCII-символов. Не включайте секреты или персональные данные. Сохраните ключ и тело запроса на своей стороне до отправки.

При повторе передавайте тот же ключ и те же данные, даже если запрос отправляет другой сервер, приложение перезапустилось или API-ключ был заменён. Ключ операции действует в пределах организации и нормализованного тела запроса.

Ситуация Ответ API
Операция завершена Исходный ответ с Idempotent-Replayed: true и прежним X-Request-ID.
Операция ещё выполняется 409 idempotency_in_progress. Подождите указанное в Retry-After время.
Ключ тот же, тело другое 409 idempotency_conflict. Исправьте соответствие ключа и операции; автоматически повторять запрос не нужно.

Срок хранения

По умолчанию результат хранится 24 часа. Изменения срока согласуются отдельно. После окончания этого срока тот же ключ может привести к новой проверке и новому списанию.

Ограничивайте автоматические повторы сроком хранения и ведите собственный журнал платёжных операций.

Сохранённые ошибки

Ошибки тоже могут сохраняться, включая завершённые ответы об исчерпанном лимите или недоступном источнике. retryable=true описывает ошибку, но не удаляет сохранённый ответ.

Если вместе с ошибкой пришёл Idempotent-Replayed: true, прекратите автоматические повторы и обработайте полученный результат. После этого можно явно создать новую проверку, если нужна более поздняя оценка. Не меняйте ключ, пока неизвестно, чем закончился первоначальный запрос.

Лимиты запросов

Где посмотреть ограничения

Лимиты определяются тарифом или индивидуальными условиями организации. Текущие значения доступны через GET /v1/usage и в разделе «Тариф и лимиты» кабинета. Числа из примеров не являются условиями вашего тарифа.

Заголовки ответа Что показывают
X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset Допустимую частоту запросов, остаток и время обновления.
X-Quota-Limit, X-Quota-Remaining, X-Quota-Reset Месячный лимит проверок, остаток и время обновления.

Время обновления передаётся в секундах Unix. Месяц определяется по UTC независимо от часового пояса браузера. Все ключи организации и запросы из кабинета используют общий лимит.

Если лимит достигнут

  • 429 rate_limit_exceeded: запросы отправляются слишком часто.
  • 429 concurrency_limit_exceeded: слишком много запросов выполняется одновременно.
  • 429 quota_exceeded: закончился месячный лимит проверок.

Учитывайте Retry-After. При исчерпанном месячном лимите ожидание может быть длительным. Повторная выдача сохранённого результата не списывает проверку ещё раз, но всё равно проходит проверку доступа, частоты и числа одновременных запросов.

Используйте очередь ограниченного размера и ограничивайте число одновременных запросов на своей стороне. Изменение тарифа влияет на новые условия, но не переписывает историю использования.

Повторы и время ожидания

Установите предел ожидания

Сервер завершает обработку не позднее чем через 12 секунд. На клиенте установите немного больший предел, например 15 секунд на попытку, чтобы учесть время передачи по сети. Целевое значение p95 составляет не более 5 секунд; это не обещание для каждого отдельного запроса.

Повторяйте с паузой и ограничением попыток

Для полученной ошибки повтор разрешён только при error.retryable=true. Учитывайте Retry-After, увеличивайте паузу между попытками и добавляйте небольшой случайный разброс, чтобы запросы не повторялись одновременно.

Ограничьте число попыток и общую продолжительность операции. Если сервер просит ждать дольше, чем может ждать пользователь, перенесите повтор в фоновую очередь. Не сокращайте указанную сервером паузу.

Если соединение оборвалось

Повторите сохранённое тело с прежним Idempotency-Key. Эти данные должны переживать перезапуск приложения.

Если вернулась сохранённая ошибка с Idempotent-Replayed: true, прекратите автоматические повторы и обработайте её. 409 idempotency_conflict требует исправления интеграции. Ответы 409 idempotency_in_progress, 429, 503 и 504 можно повторять только по правилам выше.

В обычных логах сохраняйте идентификатор запроса и публичный код ошибки. Не записывайте ключи, тела запросов, суммы или ответы источников. Примеры кода показывают ограниченные повторы для Python и TypeScript.

Ошибки API

Формат ответа

JSON
{"request_id":"merchant-order-1001-attempt-1","error":{"code":"provider_unavailable","message":"Transaction data is temporarily unavailable","retryable":true}}

X-Request-ID в заголовках соответствует request_id в JSON. Для обработки используйте стабильные code и retryable, а не текст message. Текст сообщения в примере приведён как часть ответа API.

При ошибке шлюза JSON может отсутствовать. Это означает, что результат запроса неизвестен. Сохраните исходный ключ операции: HTTP-ошибка сама по себе не доказывает, что сервер не принял запрос.

HTTP Коды Что делать
401 invalid_api_key Исправить ключ на сервере.
403 tenant_suspended, network_not_enabled Уточнить доступ у администратора организации.
409 idempotency_conflict Исправить связь ключа с телом запроса. Ошибка не допускает автоматического повтора.
409 idempotency_in_progress Дождаться Retry-After и повторить ту же операцию.
422 malformed_tx_hash, invalid_network, invalid_tron_address, invalid_expected_amount, invalid_idempotency_key, payload_too_large, validation_error Исправить неверные поля запроса.
429 rate_limit_exceeded, quota_exceeded, concurrency_limit_exceeded Учесть Retry-After, снизить нагрузку или дождаться обновления лимита.
503 provider_unavailable, rate_limiter_unavailable, api_disabled, api_not_configured Повторять только при retryable=true, с прежним ключом и ограничением попыток.
504 request_timeout После нужной паузы повторить прежний ключ и тело.
500 internal_error Применить ограниченные повторы; передать поддержке X-Request-ID.

Проверяйте Idempotent-Replayed: сохранённая ошибка не обновится от очередного повтора. Подробности в разделе повторных запросов.

Защитите интеграцию

Ключи и доступ

Обращайтесь к API с сервера. Храните ключи в защищённом хранилище и разрешайте доступ к ним только сервису интеграции. Если ключ мог попасть к посторонним, замените или отзовите его.

Не вставляйте ключ в обращение в поддержку, URL, задачу в трекере, аналитику, консоль браузера или клиентский код.

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

Данные платежей и результатов

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

Используйте точный адрес контракта токена и строковую сумму. Явно обрабатывайте null и неизвестные значения. Перед выводом в своём интерфейсе экранируйте названия организаций, ключей и данные из ответа.

Сохраняйте только необходимые для работы данные и ограничивайте доступ к деталям проверки. Для обращения в поддержку достаточно X-Request-ID и публичного кода ошибки. Ключи, суммы и полные ответы отправлять не нужно.

Справочник API

Скачать OpenAPI. Названия полей и допустимые типы взяты из контракта API. Обязательное поле может содержать null, если это разрешено его типом. Значение полей объясняется в разделах выше.

POST /v1/transaction/check

Проверка одной транзакции TRON. Передайте JSON и серверный X-API-Key. Для повтора без двойного списания используйте Idempotency-Key.

HTTP Ответ
200 Ответ получен. Проверьте результат и полноту данных.
401 Ключ API неверен или отозван.
403 У организации нет доступа к API или выбранной сети.
409 Запрос ещё обрабатывается либо ключ повторно использован с другими данными.
422 Исправьте поля запроса.
429 Достигнут лимит частоты, одновременных запросов или проверок за месяц.
503 Доступ к API закрыт или нужный сервис недоступен.
504 Истекло время обработки запроса на сервере.
500 Внутренняя ошибка. Сохраните X-Request-ID для поддержки.

GET /v1/usage

Лимиты и статистика вашей организации. Необязательный параметр days задаёт период от 1 до 90 дней. По умолчанию: 30.

HTTP Ответ
200 Ответ получен. Проверьте результат и полноту данных.
422 Исправьте поля запроса.
401 Ключ API неверен или отозван.
403 У организации нет доступа к API или выбранной сети.
429 Достигнут лимит частоты, одновременных запросов или проверок за месяц.
500 Внутренняя ошибка. Сохраните X-Request-ID для поддержки.
503 Доступ к API закрыт или нужный сервис недоступен.
504 Истекло время обработки запроса на сервере.

ErrorDetail

Поле Тип / значения Обязательно
code string Да
message string Да
retryable boolean Да

ErrorResponse

Поле Тип / значения Обязательно
request_id string Да
error ErrorDetail Да

ExposureResponse

Поле Тип / значения Обязательно
category string Да
exposure_type string Да
hops integer Да
percent string / null Да

FreshnessResponse

Поле Тип / значения Обязательно
checked_at string Да
transaction_at string / null Да
risk_data_at string / null Да
token_data_at string / null Да
max_source_age_seconds integer Да

ReasonResponse

Поле Тип / значения Обязательно
code string Да
category "transaction", "risk", "sanctions", "token", "expected" Да
severity "info", "warning", "high", "critical" Да

TransactionCheckRequest

Поле Тип / значения Обязательно
tx_hash string Да
network "tron" Да
expected_recipient string / null Нет
expected_token_contract string / null Нет
expected_amount string / null Нет

TransactionCheckResponse

Поле Тип / значения Обязательно
request_id string Да
tx_hash string Да
network "tron" Да
transaction_type string Да
transaction_category "trx_transfer", "trc10_transfer", "trc20_transfer", "smart_contract_call", "smart_contract_deploy", "staking", "voting", "governance", "resource_operation", "account_operation", "exchange", "market", "permission_update", "other", "unknown" Да
transaction_state "confirmed", "pending", "failed", "not_found", "unknown" Да
confirmations integer / null Да
required_confirmations integer Да
sender string / null Да
recipient string / null Да
token_contract string / null Да
token_symbol string / null Да
decimals integer / null Да
amount string / null Да
transfers TransferResponse[] Да
transfers_truncated boolean Да
aml_risk_level "low", "moderate", "high", "severe", "unknown" Да
sanctions_hit boolean / null Да
key_exposure ExposureResponse[] Да
token_authenticity "official", "fake", "unknown" Да
recipient_match boolean / null Да
token_match boolean / null Да
amount_match boolean / null Да
coverage "complete", "partial" Да
freshness FreshnessResponse Да
overall_state "CLEAR", "REVIEW", "HIGH_RISK", "LIMITED_DATA" Да
reasons ReasonResponse[] Да

TransferResponse

Поле Тип / значения Обязательно
index integer Да
asset_type string Да
sender string / null Да
recipient string / null Да
token_contract string / null Да
token_id string / null Да
token_symbol string / null Да
decimals integer / null Да
amount string / null Да

UsageLimitsResponse

Поле Тип / значения Обязательно
rate_limit_per_minute integer Да
max_concurrent_requests integer Да
enabled_networks string[] Да

UsagePeriodResponse

Поле Тип / значения Обязательно
start string Да
end string Да
used integer Да
reserved integer Да
limit integer Да
remaining integer Да

UsagePlanResponse

Поле Тип / значения Обязательно
code string Да
version integer Да
name string Да

UsageRecentResponse

Поле Тип / значения Обязательно
days integer Да
requests integer Да
billable integer Да
limited_data integer Да
errors integer Да
average_latency_ms integer / null Да
by_network object Да
by_overall_state object Да

UsageResponse

Поле Тип / значения Обязательно
tenant_id string Да
plan UsagePlanResponse / null Да
limits UsageLimitsResponse Да
period UsagePeriodResponse Да
recent UsageRecentResponse Да

Изменения и версии

Версия 1.0.0

Проверка транзакций TRON и статистика организации. Кабинет с доступом по приглашению, управление API-ключами, просмотр тарифа и отправка запросов от имени организации.

Ethereum и TON пока не принимаются в запросах API. В эту версию не входят API проверки кошельков, вебхуки, мониторинг и выполнение платежей.

Совместимость

Адреса API начинаются с /v1, документация находится в /docs/v1/. Файл OpenAPI создаётся из тех же моделей, что использует API, и проверяется при сборке.

Допускайте появление дополнительных полей ответа, но проверяйте типы и значения тех полей, которые использует ваша интеграция. Неизвестный код причины не означает отсутствие риска.

Для несовместимых изменений потребуется отдельная инструкция перехода на новую версию. Ссылки на документацию текущей основной версии сохраняются.

Состояние сервиса и поддержка

Что показывает индикатор

Индикатор ниже сообщает, открыт ли доступ к рабочему API. Он не выполняет проверку источников данных в реальном времени и не подтверждает их бесперебойную работу.

Поддержка сети означает, что API умеет с ней работать. У отдельной организации доступ может быть ограничен тарифом или настройками.

  • 503 api_disabled: проверки ещё не включены или временно приостановлены.
  • 503 provider_unavailable: для конкретного запроса не удалось получить необходимые данные транзакции.

Сохраните идентификатор запроса и следуйте правилам повторов.

Как связаться с нами

Напишите в поддержку ChainZap, чтобы получить приглашение, обсудить условия подключения или разобраться с ошибкой. Укажите X-Request-ID, публичный код ошибки и время по UTC.

Не отправляйте API-ключи, токены входа или полные данные транзакций и источников.

TRON поддерживается. Ethereum и TON находятся в планах.

Доступ к API

Загрузка…

Обзор