Skip to content

Formato de Errores

Todas las respuestas de error usan RFC 7807 Problem Details con Content-Type: application/problem+json.

Estructura de la respuesta

json
{
  "type":     "https://docs.comprobify.com/errors/validation-error",
  "title":    "Validation Failed",
  "status":   400,
  "code":     "VALIDATION_FAILED",
  "detail":   "La validación falló",
  "instance": "/v1/documents"
}
CampoDescripción
typeURL que enlaza a la página de documentación de este tipo de error (este sitio)
titleDescripción corta y estable del tipo de error
statusCódigo de estado HTTP (igual al estado de la respuesta)
codeClave estable legible por máquina — úsala para i18n y manejo programático
detailExplicación legible por humanos de esta ocurrencia específica
instanceLa ruta de la solicitud que produjo el error

Usar code para el manejo programático

El campo code es la clave estable sobre la que tu aplicación cliente debería decidir. Nunca cambia para una situación dada, sin importar los cambios en el texto legible de detail.

js
switch (error.code) {
  case 'CERTIFICATE_EXPIRED':
    return 'Tu certificado de firma ha expirado. Reemplázalo en la configuración del emisor.';
  case 'RESEND_COOLDOWN':
    return 'Por favor espera antes de solicitar otro correo.';
  case 'QUOTA_EXCEEDED':
    return 'Se alcanzó el límite mensual de comprobantes. Mejora tu plan.';
  default:
    return error.detail;
}

Errores de validación

Cuando code es VALIDATION_FAILED, un arreglo adicional errors lista cada campo que falló:

json
{
  "type":   "https://docs.comprobify.com/errors/validation-error",
  "title":  "Validation Failed",
  "status": 400,
  "code":   "VALIDATION_FAILED",
  "detail": "La validación falló",
  "instance": "/v1/documents",
  "errors": [
    {
      "field":   "buyer.email",
      "message": "El correo del comprador es requerido y debe ser una dirección de correo válida",
      "code":    "buyer.email",
      "value":   ""
    }
  ]
}

Cada entrada en errors tiene:

CampoDescripción
fieldLa ruta del cuerpo de la solicitud que falló (p. ej. buyer.email, items[0].taxes[0].code)
messageDescripción en inglés del fallo
codeRuta del campo sin los índices de arreglo — clave estable para localización a nivel de campo (p. ej. items.taxes.code)
valueEl valor que fue enviado

Errores del SRI

POST /:accessKey/send y GET /:accessKey/authorize son asíncronos (ver Enviar al SRI) — SRI_SUBMISSION_FAILED ya no puede devolverse como respuesta HTTP desde ninguno de los dos endpoints. Un fallo de red ahora ocurre dentro del worker en segundo plano y se registra como un evento de comprobante ERROR en su lugar; ver Envío al SRI Fallido para más detalles. La estructura de abajo se mantiene como referencia:

Cuando code es SRI_SUBMISSION_FAILED, un arreglo adicional sriMessages contiene los mensajes en bruto devueltos por el servicio SOAP del SRI:

json
{
  "type":   "https://docs.comprobify.com/errors/sri-error",
  "title":  "SRI Submission Failed",
  "status": 502,
  "code":   "SRI_SUBMISSION_FAILED",
  "detail": "El SRI rechazó el comprobante",
  "instance": "/v1/documents/1503.../send",
  "sriMessages": [
    {
      "identifier": "35",
      "message":    "ARCHIVO NO CUMPLE ESTRUCTURA XML",
      "type":       "ERROR"
    }
  ]
}

Todos los códigos de error

La mayoría de los errores llevan un code específico que es más preciso que solo el estado HTTP. Decide sobre code, no sobre status, para manejar los errores de forma programática.

400 Bad Request

CódigoCuándo ocurre
VALIDATION_FAILEDUno o más campos de la solicitud fallaron la validación — ver errors[]
CERTIFICATE_INVALIDEl archivo P12 está corrupto o no es un archivo PKCS#12 válido
CERTIFICATE_PASSWORD_INVALIDLa contraseña del P12 es incorrecta
CERTIFICATE_KEY_NOT_FOUNDNo se encontró el bag de la llave de firma dentro del P12
CERTIFICATE_EXPIREDLa fecha notAfter del certificado ya pasó
ISSUER_ID_REQUIREDFalta el encabezado X-Issuer-Id en un endpoint de comprobantes
ISSUER_ID_INVALIDX-Issuer-Id no es un entero positivo válido
INVALID_OR_EXPIRED_TOKENEl token de verificación de correo es inválido o ha expirado
DOCUMENT_TYPE_NOT_ENABLEDEl tipo de comprobante solicitado no está activo para este emisor
DOCUMENT_TYPE_NOT_SUPPORTEDEl código de tipo de comprobante no está registrado en el sistema
INVALID_STATE_TRANSITIONLa operación del comprobante no es válida para su estado actual
DOCUMENT_NOT_AUTHORIZEDLa operación (RIDE, correo) requiere que el comprobante tenga estado AUTHORIZED
SELF_REVOCATION_FORBIDDENNo se puede revocar la API key usada para autenticar esta solicitud
INVALID_FILE_UPLOADEl archivo subido falta, es del tipo incorrecto, o excede el límite de tamaño del campo (p. ej. un logo de más de 500 KB)
PROOF_FILE_LIMIT_REACHEDEl pago ya tiene el número máximo de archivos de comprobante activos (10) — elimina uno antes de subir más
VERSION_MISMATCHtermsVersion en POST /v1/tenants/agreements no coincide con la versión actualmente publicada del documento TERMS — vuelve a consultar GET /v1/agreements y presenta la versión actual antes de pedirle al usuario que acepte de nuevo
LAST_ISSUER_CANNOT_BE_REMOVEDEl tenant tiene solo un emisor activo restante — no se puede eliminar
ISSUER_HAS_DOCUMENTSEl emisor tiene comprobantes emitidos (en cualquiera de los dos ambientes) y no se puede eliminar
SEQUENTIAL_CANNOT_DECREASEnextSequential no es mayor que el valor actual del contador
TIER_CHANGE_NO_OPEl tier y el intervalo de facturación solicitados en Change Tier coinciden con los valores actuales de la suscripción
INVALID_BILLING_INTERVALbillingInterval en Create Subscription o Change Tier no es MONTHLY ni YEARLY
BAD_REQUESTOtra solicitud mal formada (respaldo — lee detail)

401 Unauthorized

CódigoCuándo ocurre
API_KEY_ENV_MISMATCHEl ambiente de la API key (sandbox/production) no coincide con el ambiente actual del tenant
UNAUTHORIZEDAPI key faltante, inválida o revocada (respaldo)

402 Payment Required

CódigoCuándo ocurre
QUOTA_EXCEEDEDSe alcanzó la cuota mensual de comprobantes — mejora de plan
BRANCH_LIMIT_REACHEDEl tenant alcanzó el número máximo de sucursales para su plan
ISSUE_POINT_LIMIT_REACHEDLa sucursal alcanzó el número máximo de puntos de emisión para este plan
WEBHOOK_ENDPOINT_LIMIT_REACHEDEl tenant alcanzó el número máximo de endpoints de webhook para su plan
DOCUMENT_TYPE_NOT_IN_TIEREl tipo de comprobante no está incluido en el plan actual del tenant — mejora de plan para habilitarlo

403 Forbidden

CódigoCuándo ocurre
ISSUER_FORBIDDENX-Issuer-Id nombra un emisor que pertenece a otro tenant
ACCOUNT_SUSPENDEDLa cuenta del tenant está suspendida — contacta a soporte
EMAIL_VERIFICATION_REQUIREDLa operación requiere que la dirección de correo esté verificada
AGREEMENT_ACCEPTANCE_REQUIREDPromoción bloqueada — uno o más acuerdos siguen en estado PENDING (revisa GET /v1/tenants/agreements, visualízalos en GET /v1/tenants/agreements/:type, acéptalos vía POST /v1/tenants/agreements)
PRODUCTION_KEY_REQUIRES_PROMOTIONNo se puede crear una API key de producción antes de promover a producción
FORBIDDENOtro fallo de permisos (respaldo — lee detail)

404 Not Found

CódigoCuándo ocurre
ISSUER_NOT_FOUNDEl ID de emisor en X-Issuer-Id o parámetro de URL no existe
SOURCE_ISSUER_NOT_FOUNDsourceIssuerId no se encontró o pertenece a otro tenant
WEBHOOK_ENDPOINT_NOT_FOUNDEl endpoint de webhook no se encontró o pertenece a otro tenant
SUBSCRIPTION_NOT_FOUNDSuscripción no encontrada
PAYMENT_NOT_FOUNDPago no encontrado, o pertenece a otro tenant
AGREEMENT_NOT_FOUNDTodavía no se ha publicado ningún documento del tipo solicitado (TERMS, PRIVACY o DPA)
NOT_FOUNDOtro recurso no encontrado (comprobante, API key — lee detail)

409 Conflict

CódigoCuándo ocurre
ALREADY_VERIFIEDSe intentó reenviar la verificación a una cuenta ya verificada
SUBSCRIPTION_ALREADY_IN_FLIGHTEl tenant ya tiene una suscripción en curso (promoción con tier, o Create Subscription del admin)
NO_ACTIVE_SUBSCRIPTIONSe solicitó Cancel o Change Tier pero el tenant no tiene una suscripción ACTIVE
TIER_CHANGE_ALREADY_PENDINGYa hay un cambio de tier/intervalo de facturación programado, o su pago ya está en curso, para esta suscripción
CANCELLATION_ALREADY_PENDINGYa hay una cancelación (DELETE /v1/subscriptions) programada para esta suscripción
CONFLICTSe reutilizó una llave de idempotencia con un payload distinto, el pago ya fue decidido, u otro conflicto

429 Too Many Requests

CódigoCuándo ocurre
RESEND_COOLDOWNSe solicitó reenviar la verificación de nuevo antes de que transcurriera el período de espera de 60 segundos
TOO_MANY_REQUESTSSe excedió el límite de tasa de la API key

500 / 502

CódigoCuándo ocurre
SRI_SUBMISSION_FAILEDEl servicio SOAP del SRI devolvió un error o un estado HTTP inesperado — ya no se expone a través de ninguna respuesta HTTP (ver Errores del SRI arriba); ahora se registra como un evento de comprobante ERROR
INTERNAL_ERRORError inesperado del servidor

Documentación de la API de Comprobify