Idempotency: evitar envíos duplicados

Idempotency en la API PSB de eConnect: cómo evitar envíos duplicados con el header X-EConnect-DocumentId.

Al enviar facturas y otros documentos a través de una API, siempre existe el riesgo de envíos duplicados. Un timeout de red, un reinicio de su aplicación o un error inesperado pueden hacer que no tenga certeza de si un documento fue efectivamente procesado. Sin protección, podría enviar el mismo documento nuevamente, resultando en facturas duplicadas.

La API PSB ofrece un mecanismo de idempotency integrado que resuelve este problema. Al enviar un documentId único con cada carga, el PSB reconoce los intentos duplicados y evita que un mismo documento se procese dos veces.

Cómo funciona

El mecanismo de idempotency se basa en el header HTTP X-EConnect-DocumentId. Al enviar un documento, agrega este header con un valor único que identifica el documento.

POST /api/v1/{partyId}/salesInvoice/send HTTP/1.1
Host: psb.econnect.eu
Authorization: Bearer {token}
Content-Type: application/xml
X-EConnect-DocumentId: 550e8400-e29b-41d4-a716-446655440000

<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
  ...
</Invoice>

El PSB procesa el documento y almacena el documentId. Si envía la misma solicitud nuevamente (por ejemplo, durante un reintento tras un timeout), el PSB reconoce que el documentId ya existe y devuelve una respuesta 409 Conflict en lugar de procesar el documento una segunda vez.

HTTP/1.1 409 Conflict

Ese 409 no es un mensaje de error en el sentido tradicional. Es una confirmación de que el documento ya fue procesado exitosamente con anterioridad. Su aplicación puede marcar la solicitud como completada con seguridad.

Requisitos para el documentId

El documentId que envía en el header X-EConnect-DocumentId debe cumplir algunas condiciones:

RequisitoExplicaciónMínimo 6 caracteresLos valores más cortos son rechazadosSin caracteres especialesCaracteres como @ y _ no están permitidosÚnico por documentoCada documento debe recibir su propio documentId

Importante: nunca utilice el número de factura como documentId. Un número de factura puede reutilizarse para una nota de crédito o una factura corregida, lo que genera conflictos. En su lugar, utilice un UUID/GUID que genere por intento de envío.

Un UUID es la opción recomendada. Está garantizado como único y es ampliamente soportado en todos los lenguajes de programación.

Correcto:   550e8400-e29b-41d4-a716-446655440000  (UUID)
Correcto:   DOC2026030800142                       (secuencia propia, si es única)
Incorrecto: INV-2026-001                           (número de factura, no usar)
Incorrecto: ab@cd                                  (caracteres especiales)
Incorrecto: abc                                    (demasiado corto)
Implementar la lógica de reintentos

La idempotency adquiere su mayor valor en combinación con lógica de reintentos. Si una llamada API falla por un error de red o un error de servidor 5xx, querrá reintentar la solicitud sin riesgo de procesamiento duplicado.

El enfoque recomendado funciona de la siguiente manera:

  1. Genere un documentId único (UUID) antes de enviar la solicitud.
  2. Envíe el documento con el header X-EConnect-DocumentId.
  3. Si recibe un 200 OK: el documento está procesado, listo.
  4. Si recibe un 409 Conflict: el documento ya fue procesado en un intento anterior, listo.
  5. Si recibe un error 5xx o un timeout: espere un momento y reintente la solicitud con el mismo documentId.
  6. Si recibe un error 4xx (excepto 409): hay un problema con la solicitud en sí. Reintentar no tiene sentido, el error debe ser corregido.

Consejo: utilice exponential backoff en los reintentos. Comience con un tiempo de espera corto (por ejemplo 1 segundo) y duplíquelo en cada intento siguiente, hasta un máximo de por ejemplo 60 segundos. El PSB en sí aplica una política de reintentos de máximo 8 intentos durante aproximadamente 35 horas en caso de errores 5xx.

¿Qué endpoints soportan idempotency?

El header X-EConnect-DocumentId se soporta en todos los endpoints con los que se cargan documentos al PSB. Los principales son:

EndpointFunciónPOST /api/v1/{partyId}/salesInvoice/sendEnviar factura de ventaPOST /api/v1/{partyId}/generic/sendEnviar documento genérico (self-billing, despatch advice)POST /api/v1/{partyId}/purchaseOrder/sendEnviar pedido

Para los endpoints de recepción (descarga de documentos), la idempotency no aplica: la recuperación de un documento es por naturaleza idempotente ya que no modifica datos.

Resumen

La idempotency es un mecanismo pequeño con un gran impacto. Al enviar consistentemente un X-EConnect-DocumentId con cada carga de documento, se protege contra envíos duplicados. En combinación con lógica de reintentos y exponential backoff, construye una integración robusta resistente a problemas de red y errores temporales del servidor.

En resumen Envíe con cada carga de documento el header X-EConnect-DocumentId con un UUID único. En un reintento, el PSB devuelve 409 Conflict si el documento ya fue procesado. Nunca utilice el número de factura como documentId.

Consultar la documentación API completa