Ошибка дубликата txn_id
Симптом. При отправке транзакции возвращается 400 с сообщением A transaction with this transaction_id already exists. в поле transaction_id, либо 409, когда два одинаковых запроса выполняются одновременно.
Причина. txn_id (это transaction_id, который вы отправляете) уникален в рамках приложения.
Didit отклоняет вторую транзакцию с тем же transaction_id и не возвращает существующую запись.
Решение.
- Генерируйте
txn_idдетерминированно на своей стороне (например, используйте ID транзакции из вашей базы данных). - При ответе
400или409с ошибкой дубликатаtransaction_idво время повторной попытки не отправляйте запрос заново, а найдите существующую транзакцию: прочитайте её черезGET /v3/transactions/{uuid}/, используяuuidиз первого ответа, или используйтеtransaction_id(uuid Didit), который webhooktransaction.createdпередаёт рядом с вашимtxn_id. - Если запрос не был повторной попыткой, присвойте новой транзакции собственный
transaction_id.
Правило не срабатывает
Симптом. Вы создали правило, которое должно совпадать, но ни в одной транзакции вrule_runs[] нет записи с matched: true.
Причины и решения.
- Приложение работает в режиме песочницы - приложение в режиме песочницы не выполняет оценку правил, AML-скрининг и биллинг и не отправляет webhook
transaction.createdиtransaction.status.updated. Обмен по Travel Rule выполняется, если он включён, с Didit Test VASP, и доставляет webhooktravel_rule.status.updatedс пометкойenvironment: sandbox.rule_runsвозвращается пустым, оценка остаётся0независимо от режима ваших правил, а транзакция остаётсяAPPROVED, если только для перевода Travel Rule с истекающим сроком не применяется вашtimeout_outcome. Проверьтеenvironmentв ответе по транзакции: значение"sandbox"означает, что она не оценивалась. См. Мониторинг транзакций в песочнице, чтобы узнать, как проверить правило перед запуском в эксплуатацию. - Режим правила
DISABLEDилиTEST- проверьте Rules → [rule] → Mode. Только правилаACTIVEвлияют на скоринг; правилаTESTвыполняются, но не влияют на статус. - Фильтр области действия исключает транзакцию - например, область
transaction_type = financeне совпадёт с транзакциямиtravelRule. - Окно агрегации короче, чем нужно - правило “20 транзакций за 30 дней” не сработает после всего 15 транзакций.
- Поле условия равно null - например, правило проверяет
counterparty.country_code, но контрагент не был отправлен. - Конвертация валюты - правило сравнивает порог с
amount_in_default_currency; если валюта по умолчанию вашего приложения отличается от валюты транзакции, сконвертированная сумма может оказаться ниже порога.
Правило срабатывает на все транзакции
Симптом. Правило срабатывает для более чем 90% транзакций, и очередь на проверку переполнена. Причина. Условия слишком широкие или пороги слишком низкие. Решение.- Добавьте фильтры
scope, чтобы сузить область действия (например, только исходящие или только определённые типы транзакций). - Повысьте пороги (суммы, количество транзакций за период).
- Переведите правило в режим
TESTна неделю - проанализируйтеrule_runs, чтобы увидеть долю совпадений, и ужесточите условия перед повторным включением.
Истекло время криптоскрининга
Симптом. Транзакция завершена со статусомstatus: APPROVED, но в массиве provider_results[] для кошелька, хеша транзакции или провайдера криптоскрининга указан status: FAILED.
Причины.
- API провайдера ненадолго стал недоступен.
- Запрос превысил время ожидания (обычно около 10 с).
- Транзакции никогда не завершаются с ошибкой из-за проблем провайдеров: обогащение выполняется по принципу максимальных усилий.
- Если конкретный провайдер регулярно выдаёт ошибки, проверьте его страницу статуса или откройте обращение в поддержку.
- Можно настроить предпочтения провайдеров в Settings → Transaction Monitoring → Providers, чтобы направлять запросы к другим провайдерам.
Отсутствует IP-обогащение
Симптом. Полеapplicant.ip_enrichment в транзакции отсутствует или заполнено частично.
Причины.
- В запросе нет
applicant.device.ip. - IP-адрес приватный или зарезервированный (не маршрутизируется).
- Все провайдеры обогащения временно недоступны.
- Получайте IP-адрес отправителя на стороне клиента или сервера и передавайте его в каждой транзакции.
- Используйте только маршрутизируемые IP-адреса: Didit без предупреждения пропускает приватные диапазоны.
- Проверьте состояние провайдеров в консоли: Settings → Status.
Несовпадение подписи webhook
Симптом. Ваш endpoint отклоняет события, потому что подпись не совпадает. Причины.- Исходное тело запроса было изменено (JSON пересериализован с другими пробелами).
- Указан неверный секрет.
- Несколько адресов назначения с одним и тем же URL - подписи различаются для каждого адреса назначения.
- Подписывайте исходное тело запроса, а не разобранный JSON. Во многих фреймворках есть промежуточное ПО для получения исходного тела.
- При компрометации секрета перевыпустите его: Webhook destinations → [destination] → Rotate secret.
- Используйте один адрес назначения на каждый URL, чтобы избежать путаницы с секретами.
Webhook не приходит
Симптом. Транзакции создаются, но webhook не приходят. Причины.- Параметр
enabledадреса назначения имеет значениеfalse. - URL недоступен из интернета.
- Адрес назначения автоматически отключён после повторных ошибок.
- Событие отсутствует в
subscribed_events.
- Отправьте тестовое событие: Webhook destinations → [destination] → Send test.
- Проверьте последние доставки: Webhooks → [destination] → Deliveries. Там видны ответы 4xx/5xx с телом и заголовками.
- Снова включите отключённые адреса назначения.
Неверная конвертация валюты
Симптом.amount_in_default_currency не совпадает с ожидаемым курсом.
Причины.
- Курс валюты - это средний рыночный курс на дату
txn_date. - Транзакции с задним числом используют исторический курс на эту дату.
- Для некоторых валют (экзотических) курсы обновляются реже.
- Для отображения используйте
amountиcurrency(исходные). - Используйте
amount_in_default_currencyтолько для внутренней проверки порогов правил. - Для аудита запись о транзакции фиксирует курс конвертации, использованный при оценке.
Контрагент не совпадает с моим списком блокировки
Симптом. Вы добавили компанию в список блокировки поvendor_data, но транзакция с этим контрагентом всё равно прошла.
Причины.
- В полезной нагрузке транзакции у контрагента нет
vendor_data, и он сохранён как внешний снимок. - Регистр
vendor_dataотличается.
- Всегда передавайте
counterparty.vendor_data, если контрагент является субъектом на вашей платформе. - Используйте одинаковый регистр везде:
vendor_dataчувствителен к регистру.
Транзакции зависают в статусе AWAITING_USER
Симптом. Транзакции остаются вAWAITING_USER, потому что пользователь так и не завершает сессию устранения.
Причины.
- Пользователь не открыл URL сессии устранения.
- Сессия устранения истекла.
- Транзакция является переводом Travel Rule, который библиотечное правило, например
travel-rule-pending-action, перевело вAWAITING_USER. Didit не создаёт сессию устранения по умолчанию для транзакции Travel Rule, поэтому, если правило не указывает собственный сценарий устранения, нет ссылки, которую можно доставить.
- Ссылку для доставки возвращает поле
remediation_session_urlв ответе по транзакции. Передайте её пользователю повторно. - Для транзакции Travel Rule урегулируйте перевод на вкладке Travel Rule, затем измените статус транзакции самостоятельно, так как урегулирование перевода само по себе не переводит транзакцию из
AWAITING_USER. - Сессии устранения следуют тому же шаблону, что и быстрый старт KYC: подпишитесь на webhook о завершении.
- Задайте в своей системе тайм-аут, чтобы помечать устаревшие транзакции как истёкшие, если устранение так и не завершилось.
Превышение лимита при создании
Симптом.429 Too Many Requests при всплесках высокой нагрузки.
Решение.
- Учитывайте заголовок
Retry-After. - Ограничивайте частоту запросов на стороне клиента при всплесках трафика.
- Обратитесь в поддержку, чтобы повысить лимиты при подтверждённом объёме трафика на продакшне.
Дальнейшие шаги
Руководство по интеграции
Полные шаблоны интеграции.
Правила
Как работает оценка правил.
Webhook
Механика webhook.