Índice de la documentación

Códigos de Error

Referencia completa de los errores que puede retornar la API y cómo manejarlos.

Formato de Respuesta de Error

Los errores siguen este formato JSON (algunos añaden campos extra, como supplier_ruc o usage):

{
"detail": "Mensaje descriptivo",
"error_code": "categoria.error_especifico"
}

El campo error_code usa el formato categoria.error para facilitar el manejo programático de errores. Las respuestas del control de cuota (por ejemplo quota_exceeded) no llevan punto. Los mensajes detail están mayormente en español; algunos de cuota y de error interno vienen en inglés: usa siempre error_code para tu lógica.

Códigos HTTP

400

Bad Request

La petición tiene un formato inválido o faltan parámetros requeridos. No reintentar.

Posibles causas:

  • •Formato de document_id incorrecto
  • •JSON malformado en el body
  • •API Key sin Clave SOL configurada (Receptor)
  • •Emisor: el RUC del document_id no coincide con el RUC de la API Key
401

Unauthorized

No se proporcionó API Key o la key es inválida. No reintentar.

Posibles causas:

  • •Header Authorization faltante
  • •API Key expirada o revocada
  • •Formato incorrecto del Bearer token
403

Forbidden

API Key válida pero sin permisos para el recurso. No reintentar.

Posibles causas:

  • •Plan sin acceso a la función (por ejemplo, PDF)
  • •Período de prueba terminado (auth.trial_expired / trial_expired)
  • •Plan mensual inactivo (plan_inactive)
404

Not Found

El recurso solicitado no existe. Es una respuesta definitiva: no reintentar.

Posibles causas:

  • •SUNAT no tiene el comprobante (sunat.document_not_found): verifica el ID y el módulo (receptor/emisor)
  • •Endpoint incorrecto
422

Unprocessable Entity

La petición es válida pero no se puede atender para este caso. Definitivo: no reintentar.

Posibles causas:

  • •CDR no disponible para ese comprobante (sunat.resource_not_available)
  • •Emisor excluido de forma permanente (sunat.supplier_excluded): omite sus comprobantes
  • •Usuario SOL sin permiso de Recibos por Honorarios (sunat.rxh_permission_required)
  • •Parámetros inválidos en el listado de RxH (rxh.*)
429

Too Many Requests

Límite excedido. Espera los segundos del header Retry-After y reintenta.

Posibles causas:

  • •Demasiadas peticiones por minuto
  • •Cuota mensual agotada (quota_exceeded): no se renueva hasta el próximo ciclo; Retry-After indica cuándo
  • •Demasiadas descargas simultáneas para un mismo RUC (sunat.ruc_concurrency_limit)
  • •Cuota del proveedor enterprise (enterprise_quota_exceeded)
500

Internal Server Error

Error interno del servidor (internal_error).

Posibles causas:

  • •Error inesperado en el servidor
  • •Reintentar con espera creciente; si persiste, contactar a soporte con el X-Correlation-ID
502

Bad Gateway

SUNAT rechazó las credenciales SOL (sunat.auth_failed). NO reintentar.

Posibles causas:

  • •Clave SOL incorrecta, cuenta SOL bloqueada o permiso no habilitado
  • •Reintentar con las mismas credenciales puede bloquear la cuenta SOL del titular
  • •Actualiza la Clave SOL de la API Key (elimínala y crea una nueva)
503

Service Unavailable

Falla pasajera o "todavía no". Reintentar respetando el header Retry-After.

Posibles causas:

  • •SUNAT no respondió o falló (sunat.request_failed, sunat.auth_unavailable): reintentar con espera creciente
  • •SUNAT todavía no tiene el XML/PDF/info (sunat.document_not_ready): reintentar en horas, no en segundos
  • •No se pudo verificar la cuota (service_unavailable): reintentar en unos segundos

Códigos de Error por Categoría

El campo error_code identifica el tipo específico de error:

auth.*

Autenticación

Errores relacionados con la API Key y permisos

CódigoHTTPMensajeAcción
auth.invalid_api_key401API Key inválida o no proporcionadaVerificar API Key en el dashboard
auth.api_key_required401Este endpoint requiere autenticación con API KeyUsar API Key (sk_live_xxx) en vez de session token
auth.trial_expired403Tu período de prueba ha terminadoNo reintentar: suscribirse a un plan o comprar una bolsa
auth.max_rucs_exceeded403Has alcanzado el límite de RUCs para tu planActualizar a un plan superior. En /enterprise/api-keys responde 400: eliminar llaves sin uso o ampliar el contrato
auth.feature_not_allowed403Función no disponible en tu plan actualActualizar plan para acceder a esta función
auth.master_key_required401Master key requerida (endpoints /enterprise/*)Enviar Authorization: Bearer mk_live_...
auth.master_key_invalid401Master key invalida o inactivaVerificar la master key; si fue rotada, usar la nueva
auth.master_key_expired401Master key expiradaSolicitar una master key nueva
auth.provider_inactive403Proveedor enterprise suspendido o terminadoContactar a IntegraCPE
auth.master_key_renew_denied403La master key no puede renovar llavesPara rotar la Clave SOL de un RUC, eliminar la API key y crear una nueva
auth.module_not_enabled403El proveedor no tiene habilitado el módulo del endpointNo reintentar: contactar a IntegraCPE para habilitar el módulo
auth.module_mismatch403La API key no es del módulo que requiere el endpointNo reintentar: usar una API key del módulo correcto
validation.*

Validación

Errores en el formato de los datos enviados

CódigoHTTPMensajeAcción
validation.bad_request400Solicitud inválidaRevisar formato del request
validation.invalid_ruc400RUC debe ser exactamente 11 dígitos numéricosValidar RUC antes de enviar
validation.invalid_document_id400Formato de documento inválidoUsar formato: {RUC}-{TipoDoc}-{Serie}-{Numero}
validation.module_not_enabled400Módulo no habilitado para este proveedor enterpriseContratar el módulo o usar uno habilitado
validation.credentials_required400Faltan credenciales SUNAT para el móduloEnviar sunat_ruc, sunat_username y sunat_password
resource.*

Recursos

El recurso pedido no existe

CódigoHTTPMensajeAcción
resource.not_found404API key no encontradaVerificar el id; una llave ya eliminada también da 404
sunat.*

SUNAT

Errores relacionados con la comunicación con SUNAT

CódigoHTTPMensajeAcción
sunat.auth_failed502SUNAT rechazó las credenciales SOL (clave incorrecta, cuenta bloqueada o permiso no habilitado)No reintentar: actualizar la Clave SOL de la API Key (eliminarla y crear una nueva). Reintentar puede bloquear la cuenta SOL
sunat.auth_unavailable503SUNAT no respondió durante la autenticaciónReintentar con espera creciente, respetando Retry-After (30 s)
sunat.request_failed503SUNAT falló al entregar el documento (500/502/503 de SUNAT)Reintentar con espera creciente (backoff), respetando Retry-After (30 s)
sunat.document_not_found404SUNAT no tiene este comprobanteNo reintentar: definitivo (ningún documento reapareció en 30 días). Verificar el ID y el módulo (receptor/emisor)
sunat.document_not_ready503SUNAT todavía no tiene resultados para este comprobanteReintentar en horas (mediana observada: 1,4 h), respetando Retry-After (1 hora). Boletas informadas por Resumen Diario: pueden responder esto de forma sostenida
sunat.resource_not_available422El recurso (normalmente el CDR) no está disponible para este comprobanteNo reintentar: es definitivo (el emisor no registró el CDR en SUNAT)
sunat.supplier_excluded422El emisor (supplier_ruc) está excluido de forma permanente por un problema conocido en SUNAT. Incluye supplier_ruc, reason y excluded_sinceNo reintentar: omitir los demás comprobantes de ese emisor. No consume cuota
sunat.ruc_concurrency_limit429Demasiadas descargas simultáneas para ese RUCReducir las peticiones concurrentes por RUC y reintentar tras Retry-After (2 s)
sunat.rxh_permission_required422El usuario SOL no tiene habilitado Recibo por Honorarios Electrónico - ConsultaNo reintentar: el titular del RUC debe habilitar la opción en SUNAT
sunat.token_expired401El token de SUNAT expiróReintentar la petición
sunat.credentials_not_configured400API Key sin credenciales SUNAT configuradasConfigurar Clave SOL en la API Key (solo Receptor)
rate_limit.*

Límite de peticiones

Límites de peticiones excedidos. Enterprise: los límites vigentes se consultan en GET /enterprise/limits

CódigoHTTPMensajeAcción
rate_limit.exceeded429Límite de peticiones excedidoEsperar según header Retry-After
rate_limit.token_auth429Límite de autenticación SUNAT excedido (el token está en caché)Esperar según header Retry-After
rxh.*

Recibos por Honorarios

Parámetros inválidos en el listado de RxH

CódigoHTTPMensajeAcción
rxh.invalid_periodo422El periodo debe tener formato YYYYMMNo reintentar: corregir el parámetro periodo
rxh.invalid_page422page debe ser >= 1No reintentar: corregir el parámetro page
cuota.*

Cuota y plan

Respuestas del control de cuota y errores generales. Su error_code no lleva punto; el cuerpo puede traer además upgrade_url, usage, limit_type y reason

CódigoHTTPMensajeAcción
quota_exceeded429Límite por minuto o cuota mensual excedidos (limit_type: per_minute o per_month; el detail viene en inglés)Esperar Retry-After. Si es per_month, ampliar plan o comprar bolsa
enterprise_quota_exceeded429Límite del proveedor enterprise excedido para este cicloEsperar al próximo ciclo o ampliar el contrato
trial_expired403Período de prueba terminado (reason: requests o days)No reintentar: suscribirse a un plan o comprar una bolsa
plan_inactive403Tu plan mensual está inactivoNo reintentar: activar el plan desde el portal
service_unavailable503No se pudo verificar la cuotaReintentar tras Retry-After (5 s)
emisor_ruc_mismatch400Módulo emisor: el RUC del document_id no coincide con el RUC de las credenciales de la API KeyNo reintentar: solo se consultan comprobantes emitidos por tu propio RUC
internal_error500Error interno no controlado (el detail viene en inglés)Reintentar con espera creciente; si persiste, contactar a soporte con el X-Correlation-ID
server.*

Servidor

Errores internos del servidor

CódigoHTTPMensajeAcción
server.key_creation_failed200Falla interna al crear una llave en el alta masiva (viene por ítem en errors[])Reintentar ese ítem; si persiste, contactar a IntegraCPE
server.service_unavailable503Servicio no disponible temporalmenteReintentar usando el header Retry-After
server.internal_error500Error interno del servidorContactar soporte si persiste

Manejo de Errores Recomendado

async function downloadXML(documentId: string) {
try {
const response = await fetch(
`https://api.integracpe.com/api/v1/sunat/receptor/xml/${documentId}`,
{
headers: {
'Authorization': 'Bearer sk_live_tu_api_key'
}
}
);
if (!response.ok) {
const error = await response.json();
const [category] = String(error.error_code).split('.');
switch (category) {
case 'auth':
if (error.error_code === 'auth.trial_expired') {
console.log('Trial expirado. Suscríbete a un plan.');
// Redirigir a página de planes
} else {
console.log('Error de autenticación:', error.detail);
}
break;
case 'sunat': {
const retryAfter = response.headers.get('Retry-After');
if (error.error_code === 'sunat.auth_failed') {
// Definitivo: la clave SOL no sirve. NO reintentar (puede bloquear la cuenta SOL)
console.log('Actualizar la Clave SOL de la API Key:', error.detail);
} else if (error.error_code === 'sunat.document_not_ready') {
// "Todavía no": reintentar en horas, no en segundos
console.log(`Aún no disponible. Reintentar en ${retryAfter}s o más`);
} else if (
error.error_code === 'sunat.request_failed' ||
error.error_code === 'sunat.auth_unavailable'
) {
console.log(`Falla pasajera de SUNAT. Reintentar en ${retryAfter}s (con backoff)`);
} else {
// document_not_found, resource_not_available, supplier_excluded: definitivos
console.log('Definitivo, no reintentar:', error.detail);
}
break;
}
case 'rate_limit':
console.log(`Rate limit. Esperar ${response.headers.get('Retry-After')}s`);
break;
case 'validation':
console.log('Error de validación:', error.detail);
// Mostrar error al usuario
break;
default:
// Cuota y otros sin prefijo con punto: quota_exceeded, enterprise_quota_exceeded...
if (error.error_code === 'quota_exceeded' || error.error_code === 'enterprise_quota_exceeded') {
console.log(`Cuota excedida. Reintentar en ${response.headers.get('Retry-After')}s`);
} else {
console.log('Error:', error.detail);
}
}
throw new Error(error.detail);
}
return await response.json();
} catch (error) {
console.error('Error de conexión:', error);
throw error;
}
}

Política de Reintentos

Reintentar

  • ✓429 - Cuota o concurrencia por RUC: esperar el header Retry-After
  • ✓503 sunat.request_failed / auth_unavailable - Falla pasajera de SUNAT: backoff, respetando Retry-After
  • ✓503 sunat.document_not_ready - Todavía no: reintentar en horas (mediana 1,4 h), no en segundos
  • ✓500 - Error interno: backoff; si persiste, soporte con X-Correlation-ID

No Reintentar

  • ✗400 / 401 / 403 - Request inválido, API Key inválida, sin permisos o trial terminado
  • ✗404 - Documento no existe en SUNAT: definitivo
  • ✗422 - CDR no disponible, emisor excluido, sin permiso RxH: definitivo
  • ✗502 sunat.auth_failed - Clave SOL rechazada: reintentar puede bloquear la cuenta SOL

Límite de peticiones y headers

La API incluye headers sobre tu uso y sobre cuándo reintentar:

HeaderDescripción
X-RateLimit-LimitLímite mensual de tu plan (peticiones por ciclo). En un 429 por cuota, el límite que se excedió
X-RateLimit-RemainingPeticiones que te quedan en el ciclo actual (0 en un 429 por cuota)
X-RateLimit-ResetMomento en que se reinicia el ciclo (timestamp Unix, en segundos)
Retry-AfterSegundos a esperar antes de reintentar (en 429 y en 503)
X-Correlation-IDIdentificador de la petición. Se devuelve en las respuestas y puedes enviarlo tú (máx. 36 caracteres alfanuméricos o guion) para trazar una llamada

Logging

Guarda el error_code completo en tus logs para facilitar el debugging. Es más útil que solo el código HTTP.

Soporte

Si encuentras un error que no puedes resolver, contacta a soporte@integracpe.com incluyendo el identificador de la petición (header X-Correlation-ID).