Esta guía es para desarrolladores que implementan la integración del plugin Bank Transfer. Cubre los patrones y decisiones que van más allá de las llamadas individuales a endpoints: idempotencia, estrategia de reintentos, manejo de estados y validación de webhooks. Para los parámetros de los endpoints y los esquemas de respuesta, consulte la Referencia de API.Documentation Index
Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
Use this file to discover all available pages before exploring further.
Idempotencia
Cada solicitud mutante (initiate, process, cancel) requiere un header
X-Idempotency. Si envía la misma clave dos veces, el plugin devuelve la respuesta original sin crear una operación duplicada.
Reglas:
- Use un UUID v4 o un identificador de negocio único (por ejemplo, su ID de orden interno)
- Longitud máxima: 255 caracteres
- Las claves tienen alcance por organización — la misma clave de dos organizaciones diferentes se trata como dos solicitudes distintas
- Las respuestas en caché se devuelven durante 24 horas
- Las respuestas reemitidas son byte-idénticas a la original (mismo código de estado y mismo body); la respuesta no expone actualmente un header para distinguir replays de ejecuciones nuevas, así que diseñe su cliente para ser seguro en cualquier caso
Detección de duplicados
Más allá de las claves de idempotencia, el plugin detecta duplicados basados en el contenido. Genera un hash a partir de la organización (del headerX-Organization-Id), senderAccountId, datos del destinatario y monto, y lo almacena en Redis durante 5 minutos (por defecto 300 segundos, configurable vía DUPLICATE_GUARD_TTL_SEC). Si ya se envió una transferencia coincidente dentro de la ventana, la solicitud es rechazada con 409 BTF-0012.
Esto captura los casos en que el cliente envía la misma transferencia con una clave de idempotencia diferente — por ejemplo, después de un timeout donde no se recibió la respuesta original.
Estrategia de reintentos
Use backoff exponencial para errores transitorios. No todos los errores deben reintentarse.
| Estado HTTP | Tipo de error | ¿Reintentar? | Notas |
|---|---|---|---|
400 | Error de validación | No | Corrija la solicitud antes de reintentar |
404 | No encontrado | No | El recurso no existe |
409 | Duplicado | No | Idempotente — use la respuesta original |
410 | Expirado | No | Cree una nueva iniciación |
422 | Regla de negocio | No | Horario, límites — la condición debe cambiar primero |
429 | Límite de tasa | Sí | Espere el valor del header Retry-After (segundos) |
500 | Error interno | Sí | Reintentar con backoff |
503 | No disponible | Sí | Reintentar con backoff |
Cuando JD SPB no está disponible, la respuesta es
HTTP 503 y el campo error.code lleva el código del proveedor JD sin transformar (por ejemplo, TRANSPORT para fallas de transporte o ACE95 para timeouts) — las fallas de la cadena JD no se envuelven en un código BTF-. Después de agotar los reintentos, la transferencia debe marcarse para reconciliación manual. No siga reintentando indefinidamente — la red JD SPB tiene horarios operativos definidos.Manejo de estados
Máquina de estados de TED OUT
Las transferencias siguen una progresión estricta. Una vez que una transferencia sale deCREATED o PENDING, no puede cancelarse.

| Estado | Significado | Acción recomendada |
|---|---|---|
CREATED | Confirmado por el usuario, en cola para envío | Mostrar “Procesando” en la interfaz; hacer polling o esperar webhook |
PENDING | Enviado a JD, esperando reconocimiento | Mostrar “Procesando”; no permitir cancelación |
PROCESSING | JD aceptó y está enrutando la transferencia | Mostrar “Procesando”; SLA típico menor a 10 minutos |
COMPLETED | Liquidado | Mostrar confirmación con confirmationNumber |
REJECTED | JD rechazó (datos inválidos, violación de regla) | Mostrar error al usuario; fondos ya liberados |
FAILED | JD inaccesible o timeout | Mostrar error; fondos ya liberados; permitir reintento si se desea |
CANCELLED | Cancelado antes del envío | Mostrar confirmación de cancelación |
Máquina de estados de iniciación
La entidadPaymentInitiation (creada por el endpoint initiate) tiene su propio ciclo de vida antes de que se cree un Transfer.

Máquina de estados de TED IN

Máquina de estados de P2P
P2P no tiene estadoPENDING. La liquidación es atómica e instantánea.

Polling vs. webhooks
Prefiera los webhooks para el estado en tiempo real. Si los webhooks aún no están configurados, haga polling enGET /v1/transfers/{transferId} con un máximo de 10 intentos usando el mismo programación de backoff que los reintentos. Después de 10 minutos sin un estado terminal (COMPLETED, REJECTED, FAILED, CANCELLED), marque la transferencia para revisión manual.
Consulte Obtener Transferencia y Webhooks.
Integración de webhooks
Para los esquemas de payload de eventos y la lista completa de eventos, consulte Webhooks.
Validación de firma
Cada solicitud de webhook incluye dos headers que su endpoint debe usar para verificar la autenticidad:X-Webhook-Signature— firma HMAC-SHA256 en formatosha256=<hex>X-Webhook-Timestamp— timestamp Unix en segundos (UTC) de cuando el plugin construyó la solicitud
X-Webhook-Timestamp), seguido de un único punto ASCII (.), seguido de los bytes crudos del cuerpo de la solicitud — exactamente como se recibieron, antes de cualquier parseo o re-codificación JSON. Use los bytes que llegaron por la red, no una versión re-serializada del objeto parseado.
Para validar:
- Lea
X-Webhook-SignatureyX-Webhook-Timestampde los headers de la solicitud. - Construya el payload firmado:
timestamp + "." + rawBody. - Calcule
HMAC-SHA256sobre el payload firmado usando suWEBHOOK_SIGNING_SECRETy codifique el resultado en hex. - Anteponga
sha256=y compare contraX-Webhook-Signatureusando una función de igualdad de tiempo constante. - Rechace la solicitud si el timestamp está fuera de una ventana de frescura aceptable (una tolerancia de 5 minutos es típica) para prevenir replay.
X-Webhook-Event-Type, X-Webhook-Routing-Key y X-Webhook-Delivery-Attempt para observabilidad — estos no forman parte del payload firmado y no deben usarse para autenticación.
JavaScript
JavaScript
Python
Python
Go
Go
Procesamiento idempotente de webhooks
Su endpoint puede recibir el mismo evento más de una vez (entrega al menos una vez). UsetransferId + event como clave compuesta para deduplicar.
Patrones de manejo de errores
Mapee los códigos de error de la API a acciones orientadas al usuario. Consulte la lista completa de errores para todos los códigos.
| Escenario | Código | Mensaje para el usuario | Acción |
|---|---|---|---|
| Fuera del horario operativo | BTF-0010 | ”Transferencias disponibles lun–vie, 06:30–17:00 (Brasilia). Próxima ventana: “ | Mostrar próxima hora disponible |
| Límite diario excedido | BTF-0011 | ”Límite diario de transferencias alcanzado. Intente mañana.” | Mostrar límite restante |
| Transferencia duplicada | BTF-0012 | ”Esta transferencia ya fue enviada.” | Devolver transferId original |
| Datos de destinatario inválidos | BTF-0001 | ”Verifique los datos del destinatario e intente nuevamente.” | Resaltar campos inválidos |
| Iniciación expirada | BTF-0202 | ”Sesión expirada. Por favor, inicie una nueva transferencia.” | Reiniciar el flujo de iniciación |
| JD SPB no disponible | TRANSPORT (HTTP 503) | “Servicio de transferencias temporalmente no disponible. Intente nuevamente en unos minutos.” | Reintentar con backoff; detecte vía 503 + código de proveedor JD sin transformar (TRANSPORT, ACE95, …), no por un prefijo BTF- |
| Midaz no disponible | BTF-2000 | ”Servicio temporalmente no disponible. Intente nuevamente en unos minutos.” | Reintentar con backoff |
Lista de verificación para salida en producción
Antes de habilitar la integración en producción:
-
X-Idempotencyse envía en cada solicitud de initiate, process y cancel - Lógica de reintentos implementada con backoff exponencial para errores 5xx/503
- Endpoint de webhook desplegado y devolviendo
200en menos de 5 segundos - Validación de firma activa en el endpoint de webhook
- Deduplicación de eventos de webhook implementada usando
transferId + event - Horario de funcionamiento validado en el lado del cliente antes de llamar a initiate (reduce los 422 innecesarios)
- Tanto
transferIdcomoconfirmationNumberalmacenados para reconciliación - Estados terminales (
COMPLETED,REJECTED,FAILED,CANCELLED) gestionados en la interfaz - Expiración de iniciación (24h) manejada — se solicita al usuario que reinicie si la ventana expira
- Readiness del servicio monitoreado en su sistema de alertas para despliegues BYOC
- Redis está disponible y monitoreado — el servicio no aceptará solicitudes si Redis es inalcanzable
-
PLUGIN_AUTH_ENABLED=trueconfigurado en producción, conPLUGIN_AUTH_ADDRESS,PLUGIN_AUTH_CLIENT_IDyPLUGIN_AUTH_CLIENT_SECRETválidos

