Ir al contenido

Reglas transversales de la API

Estas reglas aplican a más de un módulo. Si ya leíste una guía de dominio, acá está lo que esa guía da por sabido.

Los listados usan limit y offset. No hay número de página.

ParámetroTipoValor
limitnumberRegistros por página. Default 20, máximo 300
offsetnumberRegistros a saltar. Default 0

El máximo de 300 es transversal: sale de una constante compartida entre backend y frontend (PAGINATION_MAX_LIMIT), así que es el mismo tope en todos los listados. Si viste otro número en alguna guía, este es el que vale.

Un limit por encima del máximo responde 400, no lo recorta en silencio.

La respuesta trae los totales al nivel raíz, no dentro de data:

{
"success": true,
"data": [ /* ... */ ],
"total": 1247,
"limit": 20,
"offset": 0
}

Para recorrer todo: incrementa offset de a limit hasta que offset + data.length >= total. Cuando cambies un filtro, vuelve offset a 0 — si no, la primera página del nuevo filtro te sale vacía.

Si tu sistema puede reintentar una operación —por timeout, error de red o doble click— usa idempotencyKey para que el reintento no genere un segundo documento.

{
"idempotencyKey": "orden-compra-4471",
"...": "resto del payload"
}
Tipostring, máximo 128 caracteres
VigenciaPermanente. No expira
ComportamientoSi ya existe un documento emitido con esa combinación, se devuelve el original: no se crea uno nuevo ni se consume folio

Aplica a la emisión de documentos tributarios (DTE), boletas de honorarios (BHE) y boletas de terceros (BHET). El alcance no es el mismo en los tres:

DocumentoAlcance de la clave
DTE(emisor, ambiente, tipo de documento, idempotencyKey)
BHE(emisor, idempotencyKey)
BHET(emisor, idempotencyKey)

En DTE el ambiente (certificación o producción) forma parte del alcance: la misma clave puede usarse una vez en cada ambiente. Es lo que hace que, cuando pases tu emisor de certificación a producción, las claves que gastaste probando no te devuelvan documentos de prueba en lugar de emitir los reales. Las boletas de honorarios no llevan ambiente porque el SII no ofrece certificación para ellas.

La API no envuelve los errores en el sobre success/data. El formato es el nativo de NestJS:

{
"statusCode": 400,
"message": "El precio unitario debe ser al menos 1 en cada línea. 2 línea(s) tienen precio inválido.",
"error": "Bad Request"
}

Cuando falla la validación del payload, message puede ser un array de strings, uno por campo:

{
"statusCode": 400,
"message": ["El nombre del item es obligatorio", "La cantidad debe ser mayor a 0"],
"error": "Bad Request"
}

Trata message como string | string[]. Es la causa más común de que un manejador de errores rompa en el primer 400 de validación.

El campo reportar, sólo en errores del servidor

Sección titulada «El campo reportar, sólo en errores del servidor»

Las respuestas con statusCode >= 500 llevan un campo extra con el enlace a la guía del canal de reporte:

{
"statusCode": 500,
"message": "Internal server error",
"reportar": "https://docs.redcumbre.cl/guias/reportar-issue/"
}

Es aditivo: el resto del cuerpo no cambia, y un cliente que ignora el campo no se entera.

Los rechazos de cliente (4xx) NO lo llevan, a propósito. Un 400 es casi siempre un problema de la petición —un campo obligatorio que falta, un valor fuera del enum—, y ofrecer reportarlo produciría reportes de defectos que no existen. El campo aparece justo donde el error sí es nuestro.

Ver Reportar un problema.

CódigoQué pasó¿Reintentar?
400El payload no pasó validación, o una regla de negocio lo rechazóNo. Reintentar igual da lo mismo. Corregí el payload
401Falta la credencial, o no es válidaNo. Revisa el header Authorization
403La credencial es válida pero no alcanza ese endpoint, o el tenantSlug no le correspondeNo. Es un problema de roles o de servicio no habilitado
404El recurso por ID no existeNo
409Conflicto de estado: el documento ya fue emitido o anuladoNo. Consulta el estado actual antes de decidir
429Límite de tasa, respetando la ventana del límite
5xxError del lado de Redcumbre o de un servicio externo, con backoff exponencial

No hay un límite de tasa global en la API. Los límites son por caso de uso, donde el abuso tiene un costo concreto:

DóndeLímite
SMS con routeType: "otp"1 mensaje por número cada 5 minutos. Ver Envío de SMS
Verificación PIN-RUTLímite de intentos fallidos. Ver PIN-RUT

Que hoy no exista un límite global no es una invitación a paralelizar sin control: las emisiones tributarias dependen del SII, que sí tiene sus propios tiempos. Para volumen alto, la vía es Procesos Batch, no N llamadas concurrentes.

Varios endpoints de emisión aceptan un modo asíncrono: en vez del documento, devuelven un identificador de intento para consultar el estado después. Es lo que conviene cuando estás emitiendo desde una petición web y no quieres que el usuario espere al SII.

El detalle de los modos está en la guía de cada dominio.