Error de txn_id duplicado
Síntoma. Al enviar una transacción se devuelve 400 con A transaction with this transaction_id already exists. en el campo transaction_id, o 409 cuando dos solicitudes idénticas compiten entre sí.
Causa. txn_id (el transaction_id que envías) es único por aplicación.
Didit rechaza una segunda transacción con el mismo transaction_id y no devuelve el registro existente.
Solución.
- Genera
txn_idde forma determinista en tu sistema (por ejemplo, usa el ID de la transacción en tu propia base de datos). - Si recibes un
400o un409por untransaction_idduplicado durante un reintento, consulta la transacción existente en lugar de volver a enviarla: léela conGET /v3/transactions/{uuid}/usando eluuidde la primera respuesta, o usa eltransaction_id(el uuid de Didit) que el webhooktransaction.createdincluye junto a tutxn_id. - Si la solicitud no era un reintento, asigna a la nueva transacción su propio
transaction_id.
La regla no se dispara
Síntoma. Creaste una regla que debería coincidir, pero ninguna transacción la muestra enrule_runs[] con matched: true.
Causas y soluciones.
- La aplicación está en modo sandbox: una aplicación en sandbox omite la evaluación de reglas, el análisis AML, la facturación y los webhooks
transaction.createdytransaction.status.updated. Los intercambios de Travel Rule siguen ejecutándose cuando están habilitados, contra el VASP de prueba de Didit, y entregan webhookstravel_rule.status.updatedmarcados conenvironment: sandbox.rule_runsse devuelve vacío y la puntuación se queda en0, sea cual sea el modo de tus reglas, y la transacción permanece enAPPROVEDsalvo que una transferencia de Travel Rule que expira aplique tutimeout_outcome. Revisaenvironmenten la respuesta de la transacción:"sandbox"significa que nunca se evaluó. Consulta Monitorización de transacciones en sandbox para saber cómo validar una regla antes de que pase a producción. - El modo de la regla es
DISABLEDoTEST: revisa Rules → [regla] → Mode. Solo las reglasACTIVEcontribuyen a la puntuación; las reglasTESTse evalúan, pero no afectan al estado. - El filtro de alcance excluye la transacción: por ejemplo, un alcance configurado como
transaction_type = financeno coincidirá con transaccionestravelRule. - La ventana de agregación es más corta de lo necesario: una regla de “20 transacciones en 30 días” no coincidirá después de solo 15 transacciones.
- El campo de la condición es nulo: por ejemplo, tu regla comprueba
counterparty.country_code, pero no enviaste una contraparte. - Conversión de divisas: los umbrales de la regla se aplican sobre
amount_in_default_currency; si la divisa predeterminada de tu aplicación es distinta de la divisa de la transacción, el importe convertido puede quedar por debajo del umbral.
La regla se dispara con todo
Síntoma. Una regla se dispara en el 90%+ de las transacciones y tu cola de revisión se satura. Causa. Las condiciones son demasiado amplias o los umbrales demasiado bajos. Solución.- Añade filtros de
scopepara acotar su aplicación (por ejemplo, solo salientes o solo ciertos tipos de transacción). - Sube los umbrales (importes, recuentos de transacciones en un periodo determinado).
- Pon la regla en modo
TESTdurante una semana: analiza losrule_runspara ver la tasa de coincidencia y ajusta las condiciones antes de volver a habilitarla.
Se agotó el tiempo del análisis cripto
Síntoma. La transacción se completó constatus: APPROVED, pero el array provider_results[] muestra status: FAILED para una wallet, un hash de transacción o un proveedor de análisis cripto.
Causas.
- La API del proveedor no estuvo disponible temporalmente.
- La consulta superó el tiempo de espera (normalmente ~10 s).
- Las transacciones nunca fallan por problemas de un proveedor: el enriquecimiento se hace en la medida de lo posible.
- Si un proveedor concreto falla repetidamente, revisa su página de estado o abre un ticket de soporte.
- Considera configurar las preferencias de proveedores en Settings → Transaction Monitoring → Providers para redirigir a proveedores alternativos.
Falta el enriquecimiento de IP
Síntoma. Elapplicant.ip_enrichment de una transacción no aparece o está incompleto.
Causas.
- No hay
applicant.device.ipen el envío. - La IP es privada o reservada (no enrutable).
- Todos los proveedores de enriquecimiento no estuvieron disponibles temporalmente.
- Captura la IP de quien envía en tu cliente o servidor y pásala en cada transacción.
- Usa solo IP enrutables: Didit omite sin avisar los rangos privados.
- Revisa Settings → Status en la consola para ver el estado de los proveedores.
La firma del webhook no coincide
Síntoma. Tu endpoint rechaza los eventos porque la firma no coincide. Causas.- Se modificó el cuerpo sin procesar (el JSON se volvió a serializar con otros espacios en blanco).
- El secreto es incorrecto.
- Hay varios destinos con la misma URL: las firmas son distintas para cada destino.
- Calcula la firma sobre el cuerpo sin procesar de la solicitud, no sobre el JSON ya interpretado. Muchos frameworks ofrecen un middleware para el cuerpo sin procesar.
- Rota el secreto si se ha visto comprometido: Webhook destinations → [destino] → Rotate secret.
- Mantén un solo destino por URL para no confundir los secretos.
El webhook no llega
Síntoma. Se están creando transacciones, pero los webhooks nunca llegan. Causas.- El campo
enableddel destino esfalse. - La URL no es accesible públicamente.
- El destino se deshabilitó automáticamente tras fallos repetidos.
- El evento no está en
subscribed_events.
- Envía un evento de prueba: Webhook destinations → [destino] → Send test.
- Revisa las entregas recientes: Webhooks → [destino] → Deliveries. Ahí verás las respuestas 4xx/5xx con su cuerpo y sus encabezados.
- Vuelve a habilitar los destinos deshabilitados.
La conversión de divisas parece incorrecta
Síntoma.amount_in_default_currency no coincide con el tipo de cambio que esperas.
Causas.
- El tipo de cambio es el tipo medio de mercado en
txn_date. - Las transacciones con fecha retroactiva usan el tipo histórico de esa fecha.
- Algunas divisas (divisas exóticas) tienen intervalos de actualización más largos.
- Usa
amountycurrency(nativos) para mostrar los importes. - Usa
amount_in_default_currencysolo para los umbrales internos de las reglas. - Para auditoría, el registro de la transacción fija el tipo de conversión utilizado en el momento de la evaluación.
La contraparte no coincide con mi lista de bloqueo
Síntoma. Añadiste una empresa a la lista de bloqueo porvendor_data, pero una transacción con esa contraparte se procesó igualmente.
Causas.
- La contraparte del payload de la transacción no incluye
vendor_data, así que se almacena como una instantánea externa. - Las mayúsculas y minúsculas de
vendor_datano coinciden.
- Pasa siempre
counterparty.vendor_datacuando la contraparte sea una entidad de tu plataforma. - Usa las mismas mayúsculas y minúsculas en todas partes:
vendor_datadistingue entre mayúsculas y minúsculas.
Transacciones AWAITING_USER bloqueadas
Síntoma. Hay transacciones bloqueadas enAWAITING_USER porque el usuario nunca completa la sesión de remediación.
Causas.
- El usuario no abrió la URL de la sesión de remediación.
- La sesión de remediación expiró.
- La transacción es una transferencia de Travel Rule que una regla de la biblioteca, como
travel-rule-pending-action, movió aAWAITING_USER: Didit no crea su sesión de remediación predeterminada para una transacción de Travel Rule, así que, a menos que la regla indique su propio flujo de remediación, no hay ningún enlace que entregar.
- El
remediation_session_urlde la respuesta de la transacción es el enlace que debes entregar. Vuelve a enviárselo al usuario. - En una transacción de Travel Rule, resuelve la transferencia desde su pestaña Travel rule y después cambia tú mismo el estado de la transacción, porque resolver la transferencia no saca por sí solo la transacción de
AWAITING_USER. - Las sesiones de remediación siguen el mismo patrón que la guía de inicio rápido de KYC: suscríbete a los webhooks de finalización.
- Configura un tiempo de espera en tu propio sistema para que las transacciones obsoletas expiren si la remediación nunca se completa.
Límite de solicitudes al crear
Síntoma.429 Too Many Requests durante picos de alto volumen.
Solución.
- Respeta el encabezado
Retry-After. - Limita la velocidad de las solicitudes desde el cliente para el tráfico en ráfagas.
- Contacta con soporte para obtener límites más altos si tienes un volumen de producción demostrado.
Próximos pasos
Guía de integración
Patrones de integración completos.
Reglas
Cómo funciona la evaluación de reglas.
Webhooks
Funcionamiento de los webhooks.