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

Обзор

Webhook представляет собой способ, которым Didit передаёт на ваш бэкенд обновления в реальном времени при каждом изменении состояния сессии верификации, бизнес-сессии, пользователя или компании в системе поставщика либо транзакции. Подписав на нужные вам события один или несколько адресов назначения, вы сможете отреагировать сразу, как только будет готов результат, обычно в течение нескольких секунд после того, как проверяемый пользователь завершит свой сценарий. Рекомендуемый способ интеграции: webhook. Опрос GET /v3/session/{id}/decision/ поддерживается как запасной вариант, но он медленнее, требует больше запросов и пропускает события вроде data.updated, transaction.status.updated и изменения на уровне сущностей, которые отправляются только через webhook. Считайте доставку webhook источником истины и опрашивайте API только при первом запуске или для сверки. Эта глава урока по интеграции в Didit Academy начинается с обзора webhook. В уроке Academy по интеграции webhook рассматриваются с 3:12: добавление адреса назначения, выбор событий и секрет подписи, с помощью которого вы будете проверять подпись ниже.
Пользователи Cloudflare и WAF. Didit отправляет webhook с фиксированного адреса 18.203.201.92 и с заголовком User-Agent: DiditWebhook/2.0 +https://didit.me. Если ваша периферийная инфраструктура блокирует неизвестных клиентов, разрешите этот адрес в Security > WAF > Tools > IP Access Rules и выберите Разрешить для хоста-получателя webhook.

Типы событий

Используйте точное значение в массиве subscribed_events адреса назначения webhook. Подстановочные символы не поддерживаются: перечислите каждое семейство, которое хотите получать. События можно распределить по нескольким адресам назначения. Значения из этой таблицы составляют полный набор событий, на которые можно подписаться. Таких событий, как session.status.updated или kyc.completed, не существует, как и других похожих. Единственный другой вид отправки от Didit: неподписанный обратный вызов kyb.registry_search.resolved. Он уходит на webhook_url, который вы передаёте в POST /v3/kyb/search/ для каждого запроса, и никогда не отправляется на адрес назначения webhook.
Меню Business Console > API & Webhooks > Try Webhook отправляет полноценные payload для каждого из этих событий (одобрена, отклонена, на проверке, имена в Unicode, KYC/KYB, сущность, активность и транзакция). Используйте его, чтобы проверить свой endpoint перед переходом в продакшн.

Структура payload

Конверт

Все webhook используют один и тот же конверт. Поля всегда сериализуются с sort_keys=True и компактными разделителями (, / :), чтобы один и тот же payload давал одну и ту же подпись на обеих сторонах. Для событий сессии (status.updated, data.updated для обычных и бизнес-сессий) конверт дополнительно содержит:

Пример конверта сессии

Объект decision имеет ту же схему, что и ответ GET /v3/session/{id}/decision/. Канонический справочник полей по каждой функции (все свойства id_verifications[], aml_screenings[] и т. д.) см. в разделе Модели данных. Таблицы полей по функциям намеренно не дублируются здесь, чтобы схема хранилась в одном месте.

Массивы V3 (важно)

Внутри decision каждый результат по функции является массивом, чтобы один сценарий мог включать несколько экземпляров одной и той же функции (например, несколько проверок документов):
Каждый элемент содержит node_id, соответствующий графу сценария, и status для каждой функции. Не используйте устаревшие поля V2 в единственном числе (id_verification, nfc, liveness, face_match, phone, email, poa, aml, ip_analysis, database_validation): они появляются, только если адрес назначения webhook явно закреплён за webhook_version: "v2". Результаты электронной подписи находятся в signatures[] и присутствуют только тогда, когда в сценарии есть шаг электронной подписи: один элемент на каждого подписанта, с данными подписанта, подтверждением с помощью кода, сертификатом, временной меткой, хешами каждого документа и путями для скачивания, а также PDF с доказательствами. Отдельного события подписи нет: status.updated сообщает, когда их читать. См. отчёт об электронной подписи. Результаты Банковской проверки находятся в bank_verifications[], по одному элементу на каждый шаг Банковской проверки. method каждого элемента показывает, как был подтверждён счёт: open_banking (вход в банк), account_lookup (проверка счёта) или резервный способ statement либо microdeposits. Значение null, пока счёт не оценён. Когда человек выбрал Continue without your bank, continued_without_bank равен true, а continuation указывает причину. В этом случае method равен none, если только раньше не была оценена попытка: см. Когда человек не может подтвердить свой банк. При подтверждении счёта финансовые данные не считываются, поэтому financial_data.not_collected перечисляет балансы, транзакции или доходы, которые запрашивал шаг. См. Способы банковской проверки.

Блок Investigator

Для decision сессии пользователя или компании также передаётся investigator: последняя проверка Investigator для этой сессии или null, если проверок не было. Функции сбора документов, Документы KYB и Document AI, не имеют отдельного массива. Они появляются в списке features[] решения как { "feature": "DOCUMENT_AI", "node_id": "…" } (по одной записи на каждый узел). См. Document AI. Решения проверки пользователей также содержат один объект biometric_consent: требовала ли сессия явного биометрического согласия, trigger, status ответа и подтверждающие его данные. status: "pending" с reason: "BIOMETRIC_CONSENT_UNSUPPORTED_SDK" означает, что нативный SDK версии ниже 4.10.0 захватил изображение лица без шага согласия. См. Биометрическое согласие.

Ключи метода верификации личности

Каждый элемент id_verifications[] указывает, какой метод верификации личности его создал, чтобы обработчик мог выбирать ветку в зависимости от фактически полученных данных: Существующие обработчики продолжают работать без изменений: сессия с документом устанавливает verification_method в document, а остальные поля оставляет null. Типы полей описаны в Модели данных.

Одобренная сессия кошелька (status.updated)

Payload событий сущностей

Статусы сущностей: ACTIVE, FLAGGED или BLOCKED. user.data.updated и business.data.updated сохраняют поле status и добавляют массив changed_fields и словарь changes вида { field: { previous, current } }. События business.* используют vendor_business_id вместо vendor_user_id.

Payload событий транзакций

Вебхуки транзакций используют ту же инфраструктуру рассылки и тот же конверт, но идентифицируют транзакцию, а не сессию:
action_required равен null или содержит ожидающее действие пользователя (type wallet_ownership или verification_session с его url), описанное в Обязательные действия пользователя. Новые транзакции по умолчанию получают статус APPROVED. Если правило, список блокировки или сценарий меняет статус при создании, первоначальный payload transaction.created отражает этот итоговый статус. transaction.status.updated содержит ту же структуру с обновлённым status. Статусы транзакций: APPROVED, IN_REVIEW, DECLINED или AWAITING_USER; severity принимает значения UNKNOWN / LOW / MEDIUM / HIGH / CRITICAL, а direction принимает значения INBOUND / OUTBOUND. transaction.created и transaction.status.updated доставляются только для приложений в продакшн-среде. Обмены Travel Rule в песочнице отправляют travel_rule.status.updated с environment: sandbox.

Обратный вызов поиска в реестре KYB

Асинхронный поток POST /v3/kyb/search/ доставляет один дополнительный payload, который не является событием для адреса назначения. Если вы передаёте webhook_url в запросе поиска, Didit отправляет POST-запрос с обратным вызовом kyb.registry_search.resolved на этот URL после того, как реестр вернёт результат. Он отличается от вебхуков адреса назначения тремя способами:
  • Он без подписи: заголовков X-Signature* нет. Вместо них Didit добавляет X-Didit-Unsigned-Callback: true. Проверяйте его, сопоставляя request_id с идентификатором, возвращённым в ответе на запрос поиска.
  • Название события находится в event_type (а не в webhook_type), и полей application_id и environment нет.
  • timestamp и created_at являются целыми числами в формате epoch, как и у других вебхуков, но в отличие от ISO-формата created_at у endpoint поиска.
Для обратного вызова действует та же политика повторных попыток, что и для вебхуков адреса назначения: при повторах timestamp обновляется, и подпись по-прежнему отсутствует. Полную схему списка кандидатов см. в KYB Registry API.

Проверка подписи

Каждый webhook подписывается с помощью HMAC-SHA256 и secret_shared_key адреса назначения. Отправляются три заголовка подписи, чтобы вы могли выбрать тот, который работает в вашем стеке: Заголовки, которые Didit всегда отправляет: В течение 24 часов после ротации секрета подписи все доставки на этот адрес также содержат X-Signature-Previous, X-Signature-V2-Previous и X-Signature-Simple-Previous (см. Ротация секрета подписи).

Ротация секрета подписи

Ротацию секрета подписи адреса назначения вы выполняете в Business Console. В течение 24 часов после ротации каждая доставка на этот адрес содержит ещё три заголовка, подписанных заменённым секретом: Обработчик, который принимает совпадение либо по заголовку подписи, либо по его варианту с -Previous, продолжит проверку во время развёртывания нового секрета: старый секрет совпадает с заголовком -Previous, а новый совпадает с обычным заголовком. Примеры кода ниже делают именно это. Разверните новый секрет в течение 24 часов, потому что после этого проверку будет проходить только новый секрет. Поле previous_secret_expires_at в ответе GET /v3/webhook/destinations/{destination_uuid}/ показывает, когда заканчиваются эти 24 часа. Повторные попытки и повторные отправки подписываются заново текущим секретом адреса назначения в момент отправки и несут заголовки -Previous только в течение 24 часов. Повторная ротация в течение 24 часов немедленно выводит из употребления самый старый секрет: через заголовки -Previous продолжает проверяться только тот секрет, который был текущим до новой ротации, и только в течение 24 часов от новой ротации. Заголовки -Previous существуют только для адресов назначения webhook. Секрет secret_shared_key на уровне приложения, которым подписывается унаследованный webhook_url, не имеет периода перехода: его ротация с помощью rotate_secret_key в PATCH /v3/webhook/ сразу делает старый секрет недействительным.

X-Signature-Simple устарел

X-Signature-Simple аутентифицирует оболочку события, а не payload. Его каноническая строка охватывает только timestamp, session_id, status и webhook_type. Она не охватывает decision, а также resubmit_info, metadata, vendor_data и event_id. Запрос, в котором decision переписан, а эти четыре поля не тронуты, по-прежнему проходит проверку X-Signature-Simple.Для событий, которые вообще не содержат session_id, защита ещё слабее. События транзакций (transaction_id, txn_id, amount, score) и события сущностей (vendor_user_id, vendor_business_id) подписываются строкой "{timestamp}::{status}:{webhook_type}", которая не определяет, к какой транзакции или сущности относится событие. Две разные транзакции с одинаковым статусом в одну и ту же секунду получают одинаковый X-Signature-Simple. События travel_rule.status.updated, workflow.compliance_changed и transaction_rule_suggestions.created тоже не содержат status, поэтому подписываются строкой "{timestamp}:::{webhook_type}", например "{timestamp}:::travel_rule.status.updated".Если X-Signature-Simple — единственный заголовок, который вы проверяете, считайте всё, что находится вне этих четырёх полей, недоверенным и заново запрашивайте запись через API: GET /v3/session/{session_id}/decision/ для сессии, GET /v3/transactions/{transaction_id}/ для транзакции. Это авторитетный источник данных.
Это ограничение совместимости, а не то, что мы можем исправить на месте. Каноническая строка из четырёх полей является контрактом на уровне протокола: каждый получатель, который проверяет X-Signature-Simple, пересчитывает именно эти четыре поля, поэтому изменение того, что подписывает заголовок, молча сломает проверку подписи у всех них. Покрытие тела также требует описанной канонической формы JSON, которую обе стороны воспроизводят побайтно, и Didit уже предоставляет её в виде X-Signature-V2. Вместо того чтобы добавлять второй вариант, покрывающий тело, со своими правилами канонизации, заголовок остаётся без изменений и устаревает в пользу существующих вариантов, которые подписывают весь payload. Что это означает для вас:
  • На уровне передачи ничего не меняется. X-Signature-Simple продолжает отправляться в каждой доставке и вычисляется так же. Существующие верификаторы продолжают работать, а об удалении мы сообщим заранее.
  • Новые интеграции должны использовать X-Signature-V2. Он безопасен для middleware и покрывает весь payload.
  • Если вы не можете отказаться от X-Signature-Simple, проверьте его, а затем запросите запись через API, а не читайте её из тела webhook.

Зачем три варианта?

Некоторые веб-фреймворки (парсеры тела в Express, middleware в Django, API-шлюзы) незаметно перекодируют JSON до того, как ваш обработчик его прочитает. Если исходное тело содержало "José", а ваш middleware переписывает его в "José", байты меняются, хотя данные те же. Тогда X-Signature не проходит проверку. X-Signature-V2 вычисляется из канонической формы JSON (отсортированные ключи, компактные разделители, Unicode без экранирования), которую почти каждый middleware воспроизводит детерминированно. Устаревший X-Signature-Simple служит запасным вариантом на случай, когда и это не срабатывает: он подписывает только короткую строку, не зависящую от парсера. Поскольку он подписывает только эту строку и никогда тело, он не может подтвердить тело.

Рекомендуемый порядок проверки

  1. Сначала проверьте X-Signature-V2. Пересоберите JSON.parse(body) с отсортированными ключами и сохранённым Unicode, затем вычислите HMAC-SHA256(secret, canonical) и сравните результат с заголовком через timingSafeEqual.
  2. Если проверка V2 не прошла и вы можете читать необработанные байты, проверьте X-Signature по HMAC-SHA256(secret, rawBody).
  3. Только если обе проверки не прошли, используйте устаревший X-Signature-Simple с HMAC-SHA256(secret, "{timestamp}:{session_id}:{status}:{webhook_type}"). Этот вариант подтверждает только конверт: относитесь к decision в теле как к недоверенным данным и перед действием заново получите его через GET /v3/session/{session_id}/decision/.
На каждом шаге, если присутствует парный заголовок -Previous, принимайте совпадение с любым из двух заголовков (см. Ротация секрета подписи). Во всех случаях отклоняйте любой запрос, для которого abs(now - X-Timestamp) > 300, то есть если временная метка отличается от текущего времени более чем на 5 минут (в том числе если она находится в будущем), чтобы защититься от повторной отправки.

Политика повторных попыток

Если ваш endpoint отвечает кодом 5xx или 404, Didit выполняет до 2 повторных попыток с экспоненциальной задержкой:
  • 1-я повторная попытка: примерно через 1 минуту после первоначального сбоя.
  • 2-я повторная попытка: примерно через 4 минуты после 1-й повторной попытки.
После второй повторной попытки доставка отбрасывается. Каждая попытка доставки (первоначальная и повторные) фиксируется в Business Console как отдельная запись на вкладке Доставки адреса назначения, поэтому вы можете повторить или проверить любую попытку. Каждая попытка в журнале доставок адреса назначения содержит номер attempt: 1 для первой доставки события, а для каждой повторной попытки или повторной отправки номер на единицу больше номера попытки, которую она повторяет. Автоматические повторные попытки отправляются на тот URL, на который была отправлена первая попытка, даже если вы с тех пор изменили url адреса назначения. Ручная повторная отправка идёт на текущий URL адреса назначения, поэтому исправление URL также исправляет повторную отправку. Другие правила доставки, которые нужно учитывать:
  • Исходящий HTTP-запрос прерывается по тайм-ауту через 5 секунд.
  • Didit блокирует доставку на частные адреса и localhost как защиту от SSRF и никогда не переходит по редиректам. Используйте публичный HTTPS endpoint, который отвечает напрямую.
  • URL url адреса назначения, содержащий необработанный обратный слеш, управляющий символ или более одного @ в компоненте authority, отклоняется как некорректный: такой URL нельзя создать, а существующий нельзя повторно доставить или воспроизвести. Используйте простой URL вида https://host/path с не более чем одним блоком userinfo (для URL вебхуков с basic-аутентификацией).
  • Код 2xx считается успехом. Тайм-ауты и ошибки соединения можно повторить (в журнале доставок они отображаются как 504 или 503); ответы 3xx и 4xx, кроме 404, не повторяются.
  • При повторной попытке Didit пересчитывает подписи с новым X-Timestamp, поэтому пара «временная метка и подпись» всегда согласована.
  • Повторные попытки и повторные отправки подписываются текущим секретом подписи адреса назначения на момент отправки.

Порядок доставки

Didit не гарантирует порядок, в котором webhook-и поступают к вам. Каждая доставка ставится в очередь отдельно, а повторная попытка приходит через несколько минут после первой, поэтому status.updated со значением Approved может прийти раньше более раннего события со значением In Progress. Учтите это при разработке получателя:
  • Воспринимайте webhook как сигнал о том, что что-то изменилось. Если порядок важен, вызовите GET /v3/session/{session_id}/decision/ и действуйте по текущему status.
  • Никогда не позволяйте более старому событию перезаписать более новое состояние: сравнивайте created_at события с последним сохранённым для этой записи и игнорируйте более старое.
  • Выявляйте повторы по event_id, который остаётся неизменным при повторных попытках.
Didit ставит события перевода Travel Rule в очередь в определённом порядке, описанном в разделе Изменение статуса обмена Travel Rule, но повторная попытка всё же может изменить порядок их поступления.

Настройка адреса назначения

Адресами назначения можно управлять в Business Console > API & Webhooks или через Management API.
1

Создайте адрес назначения

Вызовите POST /v3/webhook/destinations/ (или нажмите Добавить адрес назначения в консоли), передав label, публичный url, webhook_version ("v3") и массив subscribed_events, в котором перечислены все семейства событий, которые должен получать этот endpoint. Требуется хотя бы одно событие, подстановочного знака не существует.
2

Сохраните secret_shared_key

Ответ на создание возвращает secret_shared_key адреса назначения. Храните его вместе с другими серверными секретами: он относится только к этому адресу назначения и служит входными данными для всех трёх вариантов подписи HMAC-SHA256. GET /v3/webhook/destinations/{destination_uuid}/ возвращает его снова для вызовов с API-ключом и для пользователей консоли, которые могут читать webhook-и.
3

Реализуйте endpoint

Откройте публичный HTTPS-маршрут POST, прочитайте необработанное тело, проверьте подпись (предпочтительно X-Signature-V2), проверьте окно временной метки, затем выполните диспетчеризацию по webhook_type. Верните 2xx, как только поставили работу в очередь, а тяжёлую обработку выполняйте асинхронно.
4

Подтвердите получение

Следите за вкладкой Доставки адреса назначения. Исправные webhook-и возвращают 200 в течение секунды или двух. Ответы 5xx и 404 запускают политику повторных попыток Didit; устойчивые сбои отбрасываются после второй повторной попытки.
5

Проверяйте с помощью Try Webhook

Используйте сценарии Try Webhook в консоли, чтобы отправить на свой endpoint полезные нагрузки со статусами «одобрена», «отклонена» и «на проверке», а также для KYB, сущностей, активности и транзакций, прежде чем включить продакшн-трафик.
Функция тестирования webhook Didit в Business Console

Отправляйте тестовые webhook прямо из Business Console, чтобы проверить свой endpoint перед запуском.

Можно создать столько адресов назначения, сколько нужно. Распространённый подход: один адрес назначения на каждого потребителя, например события KYC отправляются в ваш сервис авторизации, события KYB в сервис комплаенс-операций, транзакции в очередь антифрод-проверок. У каждого адреса назначения свой секрет, версия и список подписок, поэтому ротация секрета или неудачный деплой у одного потребителя не влияет на остальных.

Code samples

Чтобы защитить endpoint для webhook, проверяйте подлинность входящих запросов с помощью secret_shared_key адреса назначения.
Используйте X-Signature-V2. Это вариант, наиболее устойчивый к повторному кодированию в промежуточном ПО, и он полностью подтверждает подлинность тела запроса (включая decision).

Node.js / Express (рекомендуется: X-Signature-V2)

Если вы можете читать необработанные байты до того, как их обработает какой-либо парсер, исходный вариант X-Signature работает так же, но подписывает необработанное тело. Мы оставили его в разделе устаревших форматов ниже для полноты.

Python / FastAPI (рекомендуется: X-Signature-V2)

PHP / Laravel (рекомендуется: X-Signature-V2)

Настройки JSON в PHP по умолчанию не воспроизводят каноническую форму. Четыре из них нужно переопределить, и если пропустить хотя бы одну, подписываемые байты изменятся, и дайджест никогда не совпадёт: Ловушка с пустыми объектами самая коварная. В payload Didit регулярно встречаются пустые словари, например risk_view.countries.risk_scores, risk_view.crimes.risk_scores и risk_view.custom_list, поэтому преобразование туда и обратно с использованием ассоциативного массива ломает подпись на обычных одобренных сессиях, а не в каком-то редком граничном случае.
Есть ещё два момента, которые стоит знать:
  • Числа с плавающей точкой с нулевой дробной частью не требуют особой обработки в PHP. Didit сериализует их как целые числа (100.0 → 100), а json_encode в PHP записывает такое число с плавающей точкой так же, поэтому шаг shortenFloats, который нужен в приведённом выше примере для Node.js, здесь не требуется.
  • Оставьте serialize_precision равным -1 (значение по умолчанию начиная с PHP 7.1). Если ваш хостинг переопределяет его на 17, json_encode запишет 87.42 как 87.420000000000002, и каждая проверка X-Signature-V2 будет завершаться ошибкой.
Если не удаётся добиться совпадения с канонической формой, более простой запасной вариант — verifySignatureRaw выше: $request->getContent() в Laravel возвращает нетронутые байты, поэтому X-Signature работает, пока ничто перед PHP не выполняет повторное кодирование тела. Именно этот случай и призван выдерживать X-Signature-V2, поэтому V2 проверяется первым.

Тестирование

Для проверки endpoint не нужно проводить полную верификацию.
  • В Business Console > API & Webhooks > Try Webhook выберите сценарий (например, approved_full_features, declined_face_mismatch, in_review_aml_hit, business_session_approved, transaction_created, activity_created, user_status_updated) и отправьте полностью сформированный webhook на URL вашего адреса назначения.
  • Каждый сценарий подписывается теми же тремя заголовками подписи и тем же каноническим кодированием, что и боевой трафик, включая тестовые данные с Unicode-символами (approved_kyc_with_unicode), поэтому вы можете убедиться, что X-Signature-V2 работает через ваше промежуточное ПО. Тестовые доставки содержат примерные данные и помечаются дополнительным заголовком X-Didit-Test-Webhook: true и суффиксом (Test) в User-Agent, чтобы они не попадали в продакшн-состояние.
  • Если нужно отладить регрессию, повторите любую историческую доставку из вкладки Доставки адреса назначения.
Для сквозных дымовых тестов проведите реальную верификацию через тестовый сценарий в своём приложении: создаваемые в результате webhook используют ту же структуру, заголовки и политику повторных попыток, что и сценарии Try Webhook.

Examples

Одобренная сессия KYC (status.updated)

Отклонённая сессия с предупреждениями (status.updated)

Одобренная бизнес-сессия (status.updated, KYB)

Создана транзакция (transaction.created)

Изменён статус обмена по Travel Rule (travel_rule.status.updated)

travel_rule_status принимает одно из 13 статусов обмена, описанных в разделе Travel Rule. rail принимает значения INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA или EMAIL (пустая строка, пока не выбран канал или если канал не удалось определить, а также всегда для регистраций по схеме sunrise), либо TEST_VASP для тестового перевода в песочнице, на который ответил Didit Test VASP. direction принимает значения INBOUND или OUTBOUND. Событие из песочницы содержит "environment": "sandbox", а событие TEST_VASP также содержит test_vasp: true и test_vasp_scenario (сценарий, по которому был получен ответ). Когда Didit создаёт транзакцию для перевода по Travel Rule (вызов POST /v3/transactions/, регистрация по схеме sunrise после депозита, входящий запрос TRP или входящая часть при канале INTERNAL), сначала отправляется событие transaction.created для этой транзакции, а после него события travel_rule.status.updated для перевода. Правило, которое меняет статус транзакции на этом шаге, может также отправить transaction.status.updated до transaction.created. Регистрация по схеме sunrise, которая привязывается к уже созданной вами транзакции депозита, событие transaction.created не отправляет. Каждый webhook доставляется и повторяется отдельно, поэтому повторно отправленное событие может прийти после более позднего. Ключом обработчика сделайте transaction_id, а транзакцию перечитывайте, когда нужно получить её текущее состояние. Перевод, отправленный через TRUST, никогда не получает событие COMPLETED, потому что TRUST не возвращает ничего, что Didit может прочитать: перевод остаётся в статусе AWAITING_COUNTERPARTY до истечения срока подтверждения, после чего завершается со статусом EXPIRED. Через GTR, VerifyVASP и Sygna Bridge Didit получает ответ контрагента из сети, и событие отправляется после него (см. сети Travel Rule).

Изменено соответствие сценария требованиям (workflow.compliance_changed)

transition.from и transition.to принимают одно из значений: compliant, gaps_detected, pending_change, unknown_coverage или not_evaluated. severity равен actionable, когда обнаружены пробелы, indicative при ожидающемся изменении и informative, когда пробелы устранены. Didit отправляет одно событие для каждого сценария, в котором произошли изменения.

Созданы предложения по правилам транзакций (transaction_rule_suggestions.created)

kind равен ADD для нового правила, TWEAK для изменения существующего правила и DISABLE для его отключения. rule_id равен null для ADD. open_count обозначает количество предложений, которые остаются открытыми после запуска, включая новые. Настройки предложений по правилам включают или отключают этот webhook; см. webhooks транзакций.

События Investigator (investigator.*)

Двенадцать событий investigator.* используют тот же конверт (event_id, webhook_type, timestamp, created_at, application_id, environment) и те же заголовки подписи, что и все остальные события. Они содержат только идентификаторы и числовые показатели: никогда имя, причину, которую проверяющий ввёл вручную, описание или любой текст, написанный конечным пользователем. У них нет session_id; объект, к которому относится событие, указан в item.
provenance показывает, какая версия Investigator написала отчёт:
  • engine обозначает версию движка Investigator: непрозрачный идентификатор из восьми символов. Он меняется при каждом изменении движка, поэтому два отчёта с одинаковым engine написаны одним и тем же движком.
  • agent_version обозначает версию агента.
  • policy_version обозначает версию вашей политики, которой следовал отчёт.
  • model_id обозначает устаревший псевдоним, который содержит то же значение, что и engine. Читайте engine.
  • prompt_hash больше не отправляется.
item.kind указывает тип объекта (сессия, бизнес-сессия, транзакция или кейс), а item.id его идентификатор. Временные метки с суффиксом _at представляют собой строки в формате ISO 8601. Чтобы подписаться на эти события, перечислите их точные названия в subscribed_events, как и любые другие события.

Изменён статус сущности пользователя (user.status.updated)

Resubmitted session

Устаревший способ: X-Signature с исходным телом запроса

X-Signature по-прежнему отправляется с каждой доставкой. Это HMAC-SHA256 от точных байтов, которые Didit передаёт (json.dumps(..., sort_keys=True, separators=(",", ":"))). Используйте его, только если вы можете прочитать исходное тело запроса до того, как любое промежуточное ПО его изменит.

Устаревший способ: формат webhook V2

Поля ниже применяются только тогда, когда адрес назначения закреплён за webhook_version: "v2". Существует также более старая привязка "v1" (третья форма решения с полями в единственном числе) для адресов назначения, созданных до V2. Перед использованием обратитесь в поддержку. Новые интеграции должны использовать V3 (по умолчанию), которая описана выше и использует массивы во множественном числе.
Объекты для отдельных функций одинаковы в обеих версиях: адрес назначения V2 получает те же поля match_score, risk_score, score_breakdown, risk_view и review_status для каждого совпадения, а также агрегированный score, как и V3 (см. отчёт AML). Закрепление за V2 меняет место отчёта AML в decision, но не его содержимое. Если потребителю на стороне получателя по-прежнему нужны структуры V2, создайте отдельный адрес назначения, закреплённый за webhook_version: "v2", а новых потребителей оставьте на V3.

Связанные материалы

Последнее изменение 7 ноября 2026 г.