Manejo de errores: códigos HTTP, reintentos e integración robusta

Códigos de estado HTTP, respuestas de error y lógica de reintentos de la API PSB: cómo construir una integración robusta.

Toda integración con una API se encontrará tarde o temprano con errores. Una caída de red, un servidor inalcanzable, un documento con formato incorrecto: es parte del trabajo. La API PSB comunica los errores mediante códigos de estado HTTP estándar y respuestas JSON estructuradas. Además, el PSB dispone de un mecanismo de reintento integrado que gestiona automáticamente los errores temporales durante la entrega de documentos.

En este artículo aprenderás qué códigos de estado devuelve el PSB, cómo interpretar las respuestas de error, cuándo puedes reintentar con seguridad y cómo funciona el mecanismo de reintento automático del PSB.

Códigos de estado HTTP

La API PSB utiliza códigos de estado HTTP estándar para indicar el resultado de una solicitud. Los códigos de estado se dividen en dos categorías: errores del cliente (4xx) que debes corregir tú mismo y errores del servidor (5xx) que puedes reintentar.

Respuesta exitosa
CódigoSignificadoExplicación200OKLa solicitud se procesó correctamente201CreatedNuevo objeto creado (por ejemplo un hook, subscriber o documento/recurso)202AcceptedSolicitud aceptada para procesamiento asíncrono/en cola; comprueba el estado más tarde204No ContentSolicitud exitosa sin cuerpo de respuesta (por ejemplo en un DELETE o una actualización sin cuerpo)
Errores del cliente (4xx): no reintentar

Con un error 4xx el problema está en la propia solicitud. Reenviar con los mismos datos producirá el mismo resultado. Corrige la causa antes de volver a intentarlo.

CódigoSignificadoCuándoAcción400Bad RequestError de validación o error de sintaxis en el documentoRevisa el cuerpo de la solicitud. La respuesta JSON contiene detalles sobre qué salió mal401UnauthorizedNo se envió token, o el token ha expirado o es inválidoSolicita un nuevo Bearer token al Identity Server403ForbiddenEl token es válido, pero la acción no está permitida. Lo más habitual: estás usando un partyId al que tu cuenta no tiene acceso. Otras causas: bearer token caducado, subscription key no válida, o un endpoint no disponible para tu nivel de autorizaciónComprueba que usas el partyId correcto y que el usuario que obtuvo el bearer token tiene acceso a ese partyId. Si tienes dudas: obtén un nuevo token a través del Identity Server404Not FoundEl endpoint o recurso solicitado no existe (por ejemplo, un Document ID, hook o PartyID desconocido). Al enviar, esto también ocurre con la combinación "No valid delivery options. PartyId '...' not found in Peppol" (entre otros con VerstuurInvoice): el PartyId proporcionado no está (para este tipo de documento) en Peppol/SMPVerifica la URL, el Document ID y el partyId. Ante "PartyId not found in Peppol": realiza primero una búsqueda mediante queryRecipientParty o lookup.peppol.org con el ID proporcionado, luego opcionalmente revisa esquemas relacionados (por ejemplo BE 0208 frente a 9925/BE:VAT, mismo número base) -- solo recomienda un cambio de EndpointID ante un resultado de búsqueda confirmado. Sin resultado en ningún ID candidato: el destinatario no es accesible con esos identificadores; el cliente debe consultar registro u otro ID de entrega con el destinatario405Method Not AllowedEl método HTTP utilizado no está soportado en este endpointConsulta la documentación de la API para el método correcto (GET/POST/PUT/DELETE)409ConflictEl documento ya fue procesado (idempotencia)No se requiere acción: el documento se recibió correctamente antes. Consulta idempotencia413Content Too LargeEl archivo supera el tamaño máximoReduce el documento o los adjuntos. Límite IDR: 15 MB415Unsupported Media TypeFalta la cabecera Content-Type o es incorrectaUsa el tipo de contenido correcto, por ejemplo application/json cuando sea necesario422Unprocessable EntityLa solicitud es técnicamente correcta, pero el contenido no se puede procesar (por ejemplo UBL inválido, un error de validación Peppol o una regla de negocio incumplida)Verifica la estructura del documento y las reglas de negocio; la respuesta JSON suele contener detalles400 (agencias duplicadas)Esquema de identificador duplicadoDos o más identificadores con el mismo código de esquema/agencia en una sola llamada queryRecipientParty. Mensaje de error: EConnect.Psb.Models.EConnectException: 'Duplicate id agencies {code} requested.' (donde {code} es el código de agencia sin cero inicial, p.ej. esquema 0208208).Proporcionar solo un identificador por esquema por llamada. Múltiples candidatos dentro del mismo esquema: realizar llamadas separadas.

API403 Access forbidden: el mensaje de error literal [API403] Access forbidden. Please check PartyId authorization and make sure the Subscription-Key is valid puede aparecer, entre otros casos, ante un envío Peppol fallido desde Business Central ("delivery failed"), pero la causa es genérica del PSB, no específica de BC. Orden de diagnóstico:

  1. Comprueba la autorización de PartyId: ¿usas el partyId correcto y el vínculo de cuenta tiene permisos sobre esa party?
  2. Renueva el Bearer token si ha expirado o no es válido.
  3. Comprueba la Subscription-Key solo si esa cabecera sigue siendo obligatoria (legacy/Collabrr/API31) -- no como primer paso por defecto.

Nota: la mención de "Subscription-Key" en el mensaje de error no significa automáticamente que haya que renovar la clave. La autorización de PartyId y un problema de vinculación del lado de la plataforma son causas igualmente frecuentes. Si la entrega sigue fallando tras una comprobación válida de token y partyId, escala al soporte de eConnect en lugar de rotar repetidamente la Subscription-Key.

Validación del envelope SBDH (API400.USRMS1 / API400.USRMS2): estos códigos de error indican una discrepancia entre el envelope Peppol (SBDH) y el propio documento de factura electrónica. Con USRMS1, el remitente o destinatario en el envelope no coincide con los identificadores en el XML de la factura. Con USRMS2, el PSB no puede encontrar un remitente reconocible en el documento. Verifica que el EndpointID y el PartyIdentification en tu UBL coincidan con los valores proporcionados al enviar. El PSB rechaza el documento a nivel AS4 y devuelve el error al Access Point emisor.

Limitación de tasa (429): reintentable

Una excepción a la regla "solo 5xx es reintentable": 429 Too Many Requests indica limitación de tasa y es reintentable. Espera y respeta la cabecera Retry-After antes de reenviar la solicitud.

CódigoSignificadoCuándoAcción429Too Many RequestsLimitación de tasa: estás enviando demasiadas solicitudes en un periodo de tiempoEspera y respeta la cabecera Retry-After, luego reintenta
Errores del servidor (5xx): reintentar

Un error 5xx indica un problema temporal en el lado del servidor. La solicitud en sí puede ser correcta. Junto con el 429, estos son los únicos códigos de estado donde tiene sentido reintentar.

CódigoSignificadoCuándoAcción500Internal Server ErrorError inesperado del servidorReintentar con exponential backoff502Bad GatewayRespuesta inválida de un servicio ascendente; normalmente temporalReintentar con exponential backoff503Service UnavailableEl PSB no está disponible temporalmente (mantenimiento, sobrecarga)Reintentar con exponential backoff504Gateway TimeoutUn servicio ascendente no responde a tiempoReintentar con exponential backoff

Nota: el endpoint de envío acepta un máximo de 24 MB por solicitud, incluyendo la sobrecarga HTTP. Las cargas que superen este límite son rechazadas por el servidor web con un HTTP 500 en lugar de un 413, porque el rechazo ocurre antes de que la capa de aplicación realice su validación. Tenlo en cuenta con adjuntos codificados en base64: añaden aproximadamente un 33% al tamaño del archivo.

API500UH durante despliegues: el código de error API500UH (Unhandled error) puede ocurrir cuando el PSB realiza una actualización interna del servicio (despliegue de Service Fabric). En muchos casos el documento ya se entregó correctamente al destinatario, pero el paso de confirmación falla debido a la migración. El mecanismo de reintento del PSB intenta automáticamente completar los pasos restantes. Si recibes un API500UH, verifica a través de los eventos de estado si el documento fue entregado antes de reenviarlo.

Lectura de respuestas de error

Con un error 4xx la respuesta contiene un cuerpo JSON que describe el problema. Esta información te ayuda a identificar la causa rápidamente.

{
  "error": "Validation failed",
  "message": "The supplied document is not valid UBL 2.1",
  "details": [
    "cbc:InvoiceTypeCode is missing"
  ]
}

Con un error 5xx la respuesta no siempre está estructurada. Basa tu lógica de reintentos en el código de estado HTTP, no en el contenido del cuerpo.

Estrategia de reintentos para tu integración

No todos los errores merecen un reintento. La regla general es sencilla: solo los códigos de estado 5xx y los tiempos de espera de red merecen un reintento. Con errores 4xx necesitas modificar la solicitud antes de enviarla de nuevo.

Exponential backoff

La estrategia de reintentos recomendada es exponential backoff: comienza con un tiempo de espera corto y duplícalo con cada intento posterior.

IntentoTiempo de espera11 segundo22 segundos34 segundos48 segundos516 segundos632 segundos7+60 segundos (máximo)

Consejo: añade una pequeña variación aleatoria (jitter) al tiempo de espera. Si varios clientes reintentan simultáneamente después de una caída, el jitter evita que todos lleguen al servidor en el mismo momento.

Reintentos seguros con idempotencia

Combina siempre tu lógica de reintentos con el header X-EConnect-DocumentId. Al incluir el mismo documentId en cada intento, el PSB garantiza que un documento nunca se procese dos veces. Si el PSB recibe un documentId que ya fue procesado, devuelve un 409 Conflict como confirmación.

Consulta Idempotencia: prevención de envíos duplicados para la explicación completa y ejemplos de código.

Árbol de decisión
Mecanismo de reintento automático del PSB

Además de la lógica de reintentos que implementas tú mismo, el PSB tiene su propio mecanismo de reintento para la entrega de documentos. Si el PSB intenta entregar una factura u orden al destinatario y esa parte devuelve un error 5xx, el PSB reanuda automáticamente la entrega.

Entrega de documentos (facturas y órdenes)

El PSB realiza hasta 8 intentos de reintento distribuidos en aproximadamente 35 horas. Con cada intento el PSB publica un evento para que puedas seguir el progreso:

EventoSignificadoInvoiceSentRetrySe ha iniciado un nuevo intento de entrega de una facturaInvoiceSentErrorLos 8 intentos han fallado, la factura no pudo ser entregadaOrderSentRetrySe ha iniciado un nuevo intento de entrega de una ordenOrderSentErrorLos 8 intentos han fallado, la orden no pudo ser entregada

Si has configurado un webhook para estos topics, recibes una notificación con cada intento. Después de un InvoiceSentError u OrderSentError, se requiere acción manual: contacta al destinatario o escala a través de eConnect Support.

Consejo: suscríbete a los topics InvoiceSentRetry e InvoiceSentError a través de un webhook. De esta forma detectas problemas de entrega de inmediato y puedes actuar de forma proactiva.

Entrega de webhooks

Para webhooks, el PSB utiliza un programa de reintentos separado. Si tu endpoint de webhook no es accesible o no devuelve un código de estado 2xx, el PSB reintenta la entrega del evento.

ParámetroValorDuración máxima de reintento5 díasEstrategiaExponential backoffTimeout por intento100 segundosEvento por intentoHookSentRetryEvento en fallo definitivoHookSentError

El PSB espera una respuesta 2xx de tu endpoint dentro de 100 segundos. Cualquier otra respuesta (o un timeout) cuenta como un intento fallido. Por lo tanto, procesa los webhooks entrantes lo más rápido posible, confirma la recepción con un 200 OK y realiza el procesamiento pesado de forma asíncrona en un proceso en segundo plano.

Nota: si tu endpoint no es accesible durante un período prolongado, el PSB deja de reintentar después de 5 días. Los eventos perdidos aún se pueden recuperar a través del endpoint de batch. Consulta Batch hooks para más información.

Nombres de host PSB para lista blanca de red

Para integraciones que acceden a la PSB desde una red restringida (firewall, proxy, lista de permitidos), deben autorizarse tanto los nombres de host principales como los de conmutación por error. everbinding.nl es el dominio heredado de eConnect y se usa activamente para la conmutación por error de la PSB.

EntornoPrincipalConmutación por errorProducciónpsb.econnect.euapi.everbinding.nlAceptaciónaccp-psb.econnect.eutestapi.everbinding.nl

Pon en lista blanca los cuatro nombres de host en el puerto 443 (HTTPS). Sin los nombres de host de conmutación por error, una conexión PSB válida puede volverse inaccesible durante un evento de fallo, mientras que la PSB en sí sigue funcionando.

Resumen: ¿reintentable o no?
Código de estadoReintentableEstrategia200 OKNo necesarioProcesado201 CreatedNo necesarioProcesado202 AcceptedNo necesarioComprobar estado más tarde204 No ContentNo necesarioProcesado400 Bad RequestNoCorregir solicitud401 UnauthorizedNoSolicitar nuevo token403 ForbiddenNoVerificar permisos404 Not FoundNoVerificar URL/recurso405 Method Not AllowedNoVerificar método HTTP409 ConflictNoEl documento ya fue procesado413 Content Too LargeNoReducir tamaño del archivo415 Unsupported Media TypeNoCorregir cabecera Content-Type422 Unprocessable EntityNoVerificar estructura del documento/reglas de negocio429 Too Many RequestsEsperar Retry-After, exponential backoff500 Internal Server ErrorExponential backoff502 Bad GatewayExponential backoff503 Service UnavailableExponential backoff504 Gateway TimeoutExponential backoff

En resumen Los errores del cliente (4xx) requieren tu atención: corrige el problema en tu solicitud. Los errores del servidor (5xx) son temporales y se pueden reintentar con seguridad usando exponential backoff. Utiliza siempre el header X-EConnect-DocumentId para evitar el procesamiento duplicado en los reintentos. El PSB reintenta automáticamente la entrega de documentos hasta 8 veces en aproximadamente 35 horas, y los webhooks durante un máximo de 5 días.

Ver la documentación completa de la API

Relacionados