{"openapi":"3.1.0","info":{"title":"API de Ordis","version":"1.0.0","summary":"Los datos contables y tributarios de tu propia empresa, en JSON y de solo lectura.","description":"Esta API entrega, en JSON, los datos contables y tributarios que Ordis ya calculó para tu empresa: documentos tributarios, F29, F22, KPIs del mes, flujo de caja, liquidaciones, nómina, boletas de honorarios, movimientos bancarios y deudas.\n\n**Es de solo lectura.** Los 12 endpoints son GET. Ninguna llave puede crear, modificar ni borrar un dato, y nada de lo que hagas acá declara ni presenta algo ante el SII.\n\n**Cuándo usarla.** Cuando quieres tus números en otra parte: una planilla viva, un tablero, tu propio sistema o un agente de IA al que le preguntas en lenguaje natural. Si solo quieres ver tus datos, el portal de Ordis ya los muestra y no necesitas una llave.\n\n**Cómo obtener la llave.** La creas tú desde el portal, en Configuración > API Keys. Está disponible en los planes Estratégico y Avanzado con el acceso a la API habilitado; si no ves la sección, escríbenos a hola@ordis.cl y la activamos. La llave se muestra una sola vez al crearla: Ordis guarda solo su hash y no puede recuperarla después. Si la pierdes, revócala y crea otra.\n\n**Por dónde empezar.** Llama a `GET /api/v1/me`: confirma contra qué empresa quedó apuntando la llave y devuelve el catálogo de endpoints disponibles.\n\n**La empresa sale de la llave.** Ningún endpoint acepta un identificador de empresa, ni en la ruta, ni en la query, ni en el cuerpo. No hay forma de pedir datos de otra empresa.\n\n**Todo error es JSON.** Incluso una ruta que no existe: cualquier URL bajo `/api` que no corresponda a un endpoint responde 404 con `codigo: endpoint_no_encontrado`, nunca una página HTML. Si te llega HTML, no llegaste a la API.\n\n**Límites de uso.** El techo es 60 solicitudes por minuto por llave (y 240 por minuto por IP como freno anti-abuso). Cada respuesta autenticada trae los headers `RateLimit-Limit`, `RateLimit-Remaining` y `RateLimit-Reset` (segundos hasta que se libera cupo) para que te auto-regules sin llegar al 429; el 429 agrega `Retry-After`. Son aproximados: el contador vive en memoria de cada instancia serverless, así que el techo efectivo puede ser mayor y no conviene programar contra el número exacto.\n\n**Versionado.** La API se versiona en la ruta (`/api/v1`). Los cambios incompatibles van a una versión nueva bajo su propio prefijo; `v1` no cambia de forma de manera que rompa a un consumidor. Si alguna vez se deprecara una versión, se anunciará con al menos 6 meses de anticipación mediante los headers `Deprecation` y `Sunset` (RFC 8594) en sus respuestas y en esta documentación. Hoy `v1` es la versión vigente y no emite ninguno de esos dos headers.","x-when-to-use":"Úsala para leer tus propios datos desde una herramienta externa (planilla, tablero, agente de IA). No la uses para declarar impuestos, para escribir datos ni para consultar información de terceros: nada de eso existe en esta API.","x-version-policy":{"versionadoEn":"path","versionActual":"v1","resumen":"La API se versiona en la ruta (/api/v1). Un cambio incompatible se publica como una versión nueva bajo su propio prefijo, nunca mutando la forma de una versión vigente.","deprecacion":"Una versión a deprecar se anunciará con al menos 6 meses de anticipación mediante los headers Deprecation y Sunset (RFC 8594) en sus respuestas y en esta documentación. v1 es la vigente y no emite Deprecation ni Sunset.","preavisoMinimoMeses":6,"headersDeDeprecacion":["Deprecation","Sunset"]},"contact":{"name":"Ordis","email":"hola@ordis.cl","url":"https://ordis.cl/desarrolladores"},"termsOfService":"https://ordis.cl/terminos"},"servers":[{"url":"https://ordis.cl","description":"Producción"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Cuenta","description":"Identidad de la llave y catálogo de la API."},{"name":"Tributaria","description":"Documentos tributarios, F29 y F22."},{"name":"Finanzas","description":"KPIs, flujo de caja, banco y deudas."},{"name":"Personas","description":"Liquidaciones, nómina y boletas de honorarios."},{"name":"Público","description":"Endpoints sin llave, con datos que no son de ningún cliente."}],"paths":{"/api/v1/me":{"get":{"operationId":"getMe","summary":"Identidad de la llave y catálogo de endpoints.","description":"Primer endpoint que conviene consultar: confirma contra qué empresa quedó apuntando la llave (RUT, razón social, plan) y devuelve el catálogo de endpoints disponibles con sus parámetros. El meta trae además los enlaces a esta especificación y a la documentación pública.","tags":["Cuenta"],"responses":{"200":{"description":"Identidad de la llave y catálogo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaMe"}}}},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"404":{"description":"La empresa de la llave ya no existe. Caso degenerado: la fila se borró entre la validación de la llave y la consulta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/facturas":{"get":{"operationId":"listFacturas","summary":"Documentos tributarios emitidos y recibidos.","description":"Lista los documentos tributarios de la empresa con folio, contraparte y montos, paginados de a 200 y ordenados por fecha descendente. El campo id es lo que hace direccionable un documento: es el que le pasas a /api/v1/facturas/{id}/pdf. No construyas una clave con folio y tipo, porque el folio de una recibida lo pone el emisor y dos proveedores distintos pueden mandarte su documento número 1 el mismo mes. Antes de pedir un PDF, filtra por pdf_disponible: sondear uno por uno gasta tu cuota de solicitudes.","tags":["Tributaria"],"parameters":[{"name":"periodo","in":"query","required":false,"description":"Período contable en formato YYYY-MM. Sin este parámetro, devuelve todos los períodos. Un formato distinto responde 400, no un filtro vacío.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-06"},{"name":"tipo","in":"query","required":false,"description":"Dirección del documento. Sin este parámetro devuelve emitidas y recibidas.","schema":{"type":"string","enum":["emitida","recibida"]}},{"name":"page","in":"query","required":false,"description":"Número de página, de a 200 filas. Usa meta.has_more para saber si falta traer más. Fuera de rango responde 400.","schema":{"type":"integer","minimum":1,"maximum":10000,"default":1}}],"responses":{"200":{"description":"Página de documentos tributarios.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaFacturas"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/facturas/{id}/pdf":{"get":{"operationId":"getFacturaPdf","summary":"Referencia segura al PDF de un documento.","description":"Devuelve en el cuerpo una referencia segura al PDF. Para un artefacto directo aceptado, url es relativa a Ordis y el segundo request debe conservar la misma API key; expira_en y vigencia_segundos son null. Para un PDF legacy, url es firmada y dura 5 minutos: descárgala con un request limpio, sin reenviar Authorization a Storage. Responde JSON y nunca una redirección. Los tres 404 traen un campo codigo estable para que tu programa decida sin leer el texto.","tags":["Tributaria"],"parameters":[{"name":"id","in":"path","required":true,"description":"Identificador del documento. Es el campo id de cada fila de /api/v1/facturas. Un valor que no sea UUID responde 400.","schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Referencia autenticada o URL firmada al PDF.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaFacturaPdf"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"404":{"$ref":"#/components/responses/PdfNoDisponible"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/facturas/{id}/archivo":{"get":{"operationId":"downloadFacturaArtifact","summary":"Descarga un artefacto directo aceptado.","description":"Entrega los bytes privados de un PDF original, PDF cedible o XML directo aceptado. Requiere la API key también en este request; el servidor resuelve empresa, operación, ambiente e intento vigente y verifica hash y cifrado antes de responder. No acepta bucket, path ni URL aportados por el cliente.","tags":["Tributaria"],"parameters":[{"name":"id","in":"path","required":true,"description":"Identificador UUID del documento devuelto por /api/v1/facturas.","schema":{"type":"string","format":"uuid"}},{"name":"tipo","in":"query","required":true,"description":"Artefacto directo que se desea descargar.","schema":{"type":"string","enum":["pdf","cedible","xml"]}}],"responses":{"200":{"description":"Bytes verificados del artefacto. El XML firmado se sirve como ISO-8859-1.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/xml":{"schema":{"type":"string","format":"binary"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"404":{"$ref":"#/components/responses/PdfNoDisponible"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/f29":{"get":{"operationId":"listF29","summary":"Formulario 29 mensual: IVA, PPM, retenciones y total a pagar.","description":"Devuelve el F29 de cada período, con el mismo criterio que muestra el portal: si está declarado y tiene el registro del SII, esos son los valores autoritativos (fuente sii_declarado); si todavía no se declara, se devuelve el cálculo de Ordis con es_provisorio en true (fuente motor). Si citas un número con es_provisorio en true, dilo: todavía puede cambiar. En el listado sin período, meta.fuente es null porque varía mes a mes y cada elemento trae la suya.","tags":["Tributaria"],"parameters":[{"name":"periodo","in":"query","required":false,"description":"Período contable en formato YYYY-MM. Sin este parámetro, devuelve los últimos 12 períodos, del más reciente al más antiguo. Un formato distinto responde 400, no un filtro vacío.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-06"}],"responses":{"200":{"description":"Formularios 29 del período o de los últimos 12 meses.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaF29"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/f22":{"get":{"operationId":"listF22","summary":"Formulario 22 anual: resultado a pagar o devolución por año tributario.","description":"Declaración anual de renta por año tributario (el ejercicio comercial: el AT 2025 se declara en 2026). Contrato importante: indeterminado en true significa que la declaración existe pero no se puede decidir con confianza si hay pago o devolución. En ese caso los montos van en 0 y resultado.tipo es indeterminado; se debe mostrar sin valor, nunca $0. Convención de resultado_liquidacion: mayor que 0 paga, menor que 0 le devuelven, 0 cuando es indeterminado.","tags":["Tributaria"],"parameters":[{"name":"anio","in":"query","required":false,"description":"Año tributario. Sin este parámetro devuelve el historial completo, con un tope de 25 filas.","schema":{"type":"integer","minimum":2015,"maximum":2100},"example":2025}],"responses":{"200":{"description":"Declaraciones anuales de renta.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaF22"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/kpis":{"get":{"operationId":"getKpis","summary":"Ventas, gastos, impuestos del F29 y resultado del período.","description":"Los cuatro indicadores del período con su explicación en lenguaje claro y el desglose del F29 por código tributario. Salen de los mismos constructores que pinta el dashboard del portal, así que la API y la pantalla no pueden mostrar números distintos. meta.modo dice si el período está en curso (acumulado hasta hoy en Chile) o cerrado. El KPI f29 es el total a pagar del formulario (IVA más PPM más retención de honorarios más impuesto único), no solo IVA más PPM. El detalle documento a documento se pide por /api/v1/facturas.","tags":["Finanzas"],"parameters":[{"name":"periodo","in":"query","required":false,"description":"Período contable en formato YYYY-MM. Sin este parámetro, usa el mes en curso en Chile. Un formato distinto responde 400, no un filtro vacío.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-06"}],"responses":{"200":{"description":"Indicadores del período.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaKpis"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/flujo-caja":{"get":{"operationId":"getFlujoCaja","summary":"Flujo de caja del año, mes a mes.","description":"Saldo inicial, ingresos, egresos, impuestos y cotizaciones, financiamiento, flujo neto y saldo final, mes a mes. Es la misma cadena de cálculo que alimenta el flujo de caja del portal. Contrato importante: datosIncompletos viaja siempre, también en false; en true el cálculo alcanzó un tope de filas y los totales salen menores que la realidad (un saldo final subcontado es creíble y falso), así que no se debe tratar el resultado como definitivo. La fecha de corte es hoy en Chile, no UTC.","tags":["Finanzas"],"parameters":[{"name":"anio","in":"query","required":false,"description":"Año calendario. Sin este parámetro usa el año actual en Chile. El máximo aceptado es el año actual más uno, así que el techo se mueve cada primero de enero.","schema":{"type":"integer","minimum":2020},"example":2026}],"responses":{"200":{"description":"Flujo de caja del año.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaFlujoCaja"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/movimientos-banco":{"get":{"operationId":"listMovimientosBanco","summary":"Movimientos de las cartolas bancarias cargadas.","description":"Movimientos con categoría y estado de conciliación, paginados de a 200. El signo del monto manda: positivo es abono (entró plata) y negativo es cargo (salió). El campo conciliado es true solo cuando el estado es conciliado; propuesto es un match que el sistema sugirió y que nadie confirmó, y contarlo como conciliado haría creer que la cartola está cuadrada cuando no lo está. categoria (catálogo de conciliación) y categoria_fcf (flujo de caja) son dos clasificaciones distintas y pueden venir vacías.","tags":["Finanzas"],"parameters":[{"name":"periodo","in":"query","required":false,"description":"Período contable en formato YYYY-MM. Sin este parámetro, devuelve todos los períodos. Un formato distinto responde 400, no un filtro vacío.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-06"},{"name":"page","in":"query","required":false,"description":"Número de página, de a 200 filas. Usa meta.has_more para saber si falta traer más. Fuera de rango responde 400.","schema":{"type":"integer","minimum":1,"maximum":10000,"default":1}}],"responses":{"200":{"description":"Página de movimientos bancarios.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaMovimientosBanco"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/deudas":{"get":{"operationId":"listDeudas","summary":"Créditos, leasing, tarjetas y cuentas por cobrar.","description":"Compromisos financieros con su saldo, cuotas pendientes y próxima cuota, derivadas del cronograma real. La dirección de la plata la define naturaleza, no tipo: pasivo significa que la empresa debe y activo que le deben. Sumar saldo_actual sin mirar naturaleza mezcla deuda con cobranza. Una tarjeta rotativa no tiene cronograma: devuelve 0 cuotas pendientes y proxima_cuota en null. Tope de 200 filas y SIN paginación: este endpoint no acepta page, así que un meta.has_more en true significa que la respuesta viene truncada y no hay página siguiente que pedir. Para llegar al resto, acota el conjunto con el parámetro estado.","tags":["Finanzas"],"parameters":[{"name":"estado","in":"query","required":false,"description":"Filtra por estado de la deuda. Sin este parámetro devuelve todas.","schema":{"type":"string","enum":["activo","pagado","cancelado"]}}],"responses":{"200":{"description":"Deudas y cuentas por cobrar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaDeudas"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/liquidaciones":{"get":{"operationId":"listLiquidaciones","summary":"Liquidaciones de sueldo aprobadas.","description":"Solo liquidaciones aprobadas, a propósito: un borrador es un cálculo en revisión que todavía puede cambiar, y exponerlo haría que una integración externa reporte sueldos que después no coinciden con lo pagado. costo_empleador incluye los aportes de cargo de la empresa (SIS, aporte reforma, cesantía empleador, mutual y SANNA), no solo los haberes.","tags":["Personas"],"parameters":[{"name":"periodo","in":"query","required":false,"description":"Período contable en formato YYYY-MM. Sin este parámetro, devuelve los últimos 3 períodos que tengan liquidaciones aprobadas (no los 3 meses calendario anteriores: un mes sin nómina no cuenta). Un formato distinto responde 400, no un filtro vacío.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-06"}],"responses":{"200":{"description":"Liquidaciones aprobadas.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaLiquidaciones"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/trabajadores":{"get":{"operationId":"listTrabajadores","summary":"Nómina completa con estado por trabajador.","description":"Devuelve la nómina completa por defecto, con el estado en cada fila: un trabajador con licencia o de vacaciones sigue siendo parte de la nómina y sigue costando, así que filtrarlo por defecto daría un headcount y un costo laboral equivocados. sueldo_base es el sueldo base contratado y no incluye gratificación, horas extra, bonos ni aportes del empleador; para lo que efectivamente se pagó un mes, la fuente es /api/v1/liquidaciones. Tope de 500 filas y SIN paginación: este endpoint no acepta page, así que un meta.has_more en true significa que la respuesta viene truncada y no hay página siguiente que pedir. Para llegar al resto, acota el conjunto con el parámetro estado.","tags":["Personas"],"parameters":[{"name":"estado","in":"query","required":false,"description":"Filtra por estado del trabajador. Sin este parámetro devuelve la nómina completa.","schema":{"type":"string","enum":["activo","licencia","vacaciones","desvinculado"]}}],"responses":{"200":{"description":"Nómina de la empresa.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaTrabajadores"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/v1/boletas-honorarios":{"get":{"operationId":"listBoletasHonorarios","summary":"Boletas de honorarios recibidas, con retención y estado.","description":"Las boletas que emiten los prestadores de la empresa y sobre las que la empresa retiene: son las que alimentan la retención de honorarios del F29. Se devuelven todas por defecto, incluidas las anuladas, porque omitirlas dejaría al consumidor sumando retención de boletas que el prestador dio de baja. Solo las vigente cuentan para retención. El folio de una boleta es por emisor, así que la llave real es la combinación de RUT del emisor, folio y período, nunca el folio solo.","tags":["Personas"],"parameters":[{"name":"periodo","in":"query","required":false,"description":"Período contable en formato YYYY-MM. Sin este parámetro, devuelve todos los períodos. Un formato distinto responde 400, no un filtro vacío.","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-06"},{"name":"estado","in":"query","required":false,"description":"Filtra por estado de la boleta. Sin este parámetro devuelve todas.","schema":{"type":"string","enum":["vigente","anulada","rechazada"]}},{"name":"page","in":"query","required":false,"description":"Número de página, de a 200 filas. Usa meta.has_more para saber si falta traer más. Fuera de rango responde 400.","schema":{"type":"integer","minimum":1,"maximum":10000,"default":1}}],"responses":{"200":{"description":"Página de boletas de honorarios.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RespuestaBoletasHonorarios"}}}},"400":{"$ref":"#/components/responses/SolicitudInvalida"},"401":{"$ref":"#/components/responses/LlaveInvalida"},"403":{"$ref":"#/components/responses/AccesoNoHabilitado"},"429":{"$ref":"#/components/responses/LimiteDeSolicitudes"},"500":{"$ref":"#/components/responses/ErrorInterno"},"503":{"$ref":"#/components/responses/AmbienteNoDisponible"}}}},"/api/health":{"get":{"operationId":"getHealth","summary":"Estado del servicio.","description":"Chequeo de salud público, sin llave y sin datos de ningún cliente. Responde 200 cuando el servicio está sano y 503 cuando está degradado; el cuerpo es el mismo en ambos casos y trae el detalle en status.","tags":["Público"],"security":[],"responses":{"200":{"description":"El servicio responde y la base está accesible.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstadoServicio"}}}},"503":{"description":"El servicio responde pero está degradado (status queda en degraded).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstadoServicio"}}}}}}},"/api/indicadores":{"get":{"operationId":"getIndicadores","summary":"UF, UTM y dólar observado del día.","description":"Indicadores económicos públicos de Chile, sin llave y sin datos de ningún cliente. El campo fuente dice de dónde salió el valor: api (consulta fresca), cache (valor guardado, con su antigüedad en cache_age_ms) o fallback (valores de respaldo del sistema, con cache_age_ms en -1 y el dólar en 0). La respuesta se cachea en el CDN por una hora.","tags":["Público"],"security":[],"responses":{"200":{"description":"Indicadores vigentes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Indicadores"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Llave de la empresa en el header `Authorization: Bearer <llave>`.\n\nFormato: el prefijo fijo `ordis_sk_` seguido de 43 caracteres base64url, 52 en total. El patrón exacto es `^ordis_sk_[A-Za-z0-9_-]{43}$` y se valida antes de tocar la base, así que cualquier otra forma responde 401 sin consultar nada.\n\nLa llave la crea el cliente en el portal (Configuración > API Keys) y se muestra una sola vez. Guárdala en una variable de entorno: nunca en el código, nunca en un archivo que se commitea. Si se filtró, revócala desde el portal y crea otra.\n\nEl acceso se re-evalúa en cada solicitud (plan, estado de la empresa y flag de habilitación), no al crear la llave: una llave válida puede empezar a responder 403 sin haber sido revocada."}},"responses":{"SolicitudInvalida":{"description":"Un parámetro está mal formado: un periodo que no es YYYY-MM, un page que no es entero o pasa de 10.000, un valor fuera del enum, un anio fuera de rango, o un identificador que no es UUID. El mensaje nombra el parámetro.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"LlaveInvalida":{"description":"Llave ausente, mal formada, inexistente o revocada. Campo `codigo`: `llave_invalida`.\n\nLas cuatro causas devuelven exactamente la misma respuesta, a propósito: quien tenga una llave no puede sondear el estado de otras. Si la query que busca la llave falla, también responde 401 (fail-closed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Llave inválida","codigo":"llave_invalida"}}}},"AccesoNoHabilitado":{"description":"La llave es válida pero la empresa no tiene el acceso habilitado: plan insuficiente, acceso a la API apagado, empresa de demostración o empresa fuera de operación. Campo `codigo`: `acceso_no_habilitado`.\n\nLas causas son indistinguibles entre sí, por el mismo motivo que el 401. Si te aparece de un día para otro sin haber tocado nada, escribe a hola@ordis.cl.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Acceso no habilitado","codigo":"acceso_no_habilitado"}}}},"LimiteDeSolicitudes":{"description":"Se superó el límite de solicitudes. Campo `codigo`: `limite_de_solicitudes`.\n\nLos límites son aproximadamente 60 solicitudes por minuto por llave y 240 por minuto por dirección IP, en una ventana de 60 segundos. Son aproximados a propósito: el contador vive en memoria de cada instancia del servidor, así que el techo efectivo puede ser mayor y no conviene programar contra el número exacto. Espera lo que indique el header Retry-After y reintenta.\n\nCuando el límite chocado es el de la llave, la respuesta trae además los headers `RateLimit-Limit`, `RateLimit-Remaining` (0 en este caso) y `RateLimit-Reset`, los mismos que acompañan a cada respuesta con éxito para que puedas auto-regularte antes de llegar acá. El 429 por IP solo trae `Retry-After`: llega antes de validar la llave, así que todavía no hay una cuota de cliente que reportar.","headers":{"Retry-After":{"description":"Segundos que conviene esperar antes de reintentar. Hoy siempre 60.","schema":{"type":"string"}},"RateLimit-Limit":{"description":"Techo de solicitudes por llave en la ventana (60). Presente en el 429 por llave y en cada respuesta con éxito.","schema":{"type":"integer"}},"RateLimit-Remaining":{"description":"Solicitudes que te quedan en la ventana, contando esta ya consumida (RFC RateLimit-Remaining). El último request permitido reporta 0, igual que el 429 por llave. Presente también en cada respuesta con éxito.","schema":{"type":"integer"}},"RateLimit-Reset":{"description":"Segundos hasta que se libera cupo (sale de la ventana la solicitud más antigua). Presente en el 429 por llave y en cada respuesta con éxito.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Demasiadas solicitudes. Intenta de nuevo en un minuto.","codigo":"limite_de_solicitudes"}}}},"ErrorInterno":{"description":"Falla al obtener los datos. El mensaje es genérico por diseño y no expone detalle interno. Es reintentable: si persiste, escribe a hola@ordis.cl.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"AmbienteNoDisponible":{"description":"El servicio de datos no está disponible en este ambiente. Campo `codigo`: `ambiente_no_disponible` cuando lo detecta el gate de autenticación.\n\nLa misma condición detectada dentro de un endpoint responde el mismo texto sin `codigo`. Trata el 503 por su status, no por el campo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Servicio no disponible en este ambiente","codigo":"ambiente_no_disponible"}}}},"PdfNoDisponible":{"description":"No hay un PDF que entregar. El campo `codigo` distingue los tres casos y es estable: el texto de `error` puede cambiar, el código no.\n\n- `documento_no_encontrado`: el documento no existe, o no es de tu empresa. Los dos casos comparten respuesta a propósito, para que la API no sirva de oráculo sobre documentos ajenos.\n- `pdf_no_disponible`: el documento es tuyo, pero todavía no tenemos su PDF. Filtra por `pdf_disponible` en el listado para evitar este caso.\n- `pdf_ambiguo`: hay PDF pero no se puede determinar con certeza cuál corresponde (una factura y una nota de crédito pueden compartir folio). Preferimos decirlo antes que entregar el documento equivocado. Si te pasa, escríbenos.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorConCodigoPdf"},"example":{"error":"Documento no encontrado.","codigo":"documento_no_encontrado"}}}}},"schemas":{"Error":{"type":"object","title":"Error","description":"Forma única de todos los errores de la API. Siempre es JSON con content-type application/json.","required":["error"],"properties":{"error":{"type":"string","description":"Mensaje en español pensado para una persona. Puede cambiar sin aviso: no lo uses como condición en tu código."},"codigo":{"type":"string","description":"Identificador estable de la causa, pensado para que tu programa decida sin leer el texto. No todas las respuestas lo traen: hoy lo emiten el gate de autenticación (llave_invalida, acceso_no_habilitado, limite_de_solicitudes, ambiente_no_disponible) y los 404 del PDF de un documento."},"documentacion":{"type":"string","format":"uri","description":"Enlace a la documentación pública. Lo agregan los errores de plataforma (una ruta que no existe, una llamada sin credencial a una ruta que sí la exige) para que quien se equivocó de URL tenga adónde ir. Los errores de los endpoints de datos no lo traen."},"openapi":{"type":"string","format":"uri","description":"Enlace a esta especificación. Acompaña a documentacion donde aparece."}},"additionalProperties":true},"ErrorConCodigoPdf":{"allOf":[{"$ref":"#/components/schemas/Error"},{"type":"object","required":["codigo"],"properties":{"codigo":{"type":"string","enum":["documento_no_encontrado","pdf_no_disponible","pdf_ambiguo"],"description":"Códigos estables del PDF de un documento."}}}]},"EndpointCatalogo":{"type":"object","required":["ruta","parametros","descripcion"],"properties":{"ruta":{"type":"string","description":"Ruta del endpoint, con {id} donde va un identificador."},"parametros":{"type":"array","items":{"type":"string"},"description":"Nombres de los parámetros de query que acepta."},"descripcion":{"type":"string","description":"Qué devuelve, en una línea."}}},"RespuestaMe":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["rut","razon_social","plan_contable","endpoints"],"properties":{"rut":{"type":["string","null"],"description":"RUT de la empresa, con puntos y guion."},"razon_social":{"type":["string","null"]},"plan_contable":{"type":["string","null"],"description":"Tier comercial contratado. Solo los planes Estratégico y Avanzado (o sus nombres antiguos) llegan a usar la API."},"endpoints":{"type":"array","items":{"$ref":"#/components/schemas/EndpointCatalogo"},"description":"Catálogo de lo que esta llave puede pedir."}}},"meta":{"type":"object","required":["version"],"properties":{"version":{"type":"string","const":"v1"},"openapi":{"type":"string","format":"uri","description":"Esta especificación, en JSON."},"documentacion":{"type":"string","format":"uri","description":"Página pública con la guía de uso."}}}}},"Factura":{"type":"object","required":["id","folio","tipo","tipo_documento","fecha","rut_contraparte","razon_social_contraparte","neto","iva","total","exento","periodo","pdf_disponible"],"properties":{"id":{"type":"string","format":"uuid","description":"Identificador del documento. Es el que se usa en /api/v1/facturas/{id}/pdf."},"folio":{"type":["integer","null"],"description":"Folio del documento. En las recibidas lo pone el emisor, así que se repite entre proveedores."},"tipo":{"type":["string","null"],"description":"emitida o recibida."},"tipo_documento":{"type":["string","null"],"description":"Tipo de documento tributario (factura, nota de crédito, boleta y otros)."},"fecha":{"type":["string","null"],"format":"date","description":"Fecha de emisión."},"rut_contraparte":{"type":["string","null"]},"razon_social_contraparte":{"type":["string","null"]},"neto":{"type":"number","description":"Monto neto en pesos."},"iva":{"type":"number","description":"IVA en pesos."},"total":{"type":"number","description":"Total en pesos."},"exento":{"type":"number","description":"Monto exento en pesos."},"periodo":{"type":["string","null"],"pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"pdf_disponible":{"type":"boolean","description":"Si es true, /api/v1/facturas/{id}/pdf va a devolver una URL. Aplica exactamente la misma regla que ese endpoint, así que sirve para filtrar antes de pedir."}}},"RespuestaFacturas":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Factura"}},"meta":{"type":"object","required":["periodo","tipo","page","limit","has_more"],"properties":{"periodo":{"type":["string","null"]},"tipo":{"type":["string","null"]},"page":{"type":"integer"},"limit":{"type":"integer","const":200},"has_more":{"type":"boolean","description":"Si es true, hay una página siguiente."}}}}},"RespuestaFacturaPdf":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["id","folio","tipo","tipo_documento","periodo","url","expira_en","vigencia_segundos"],"properties":{"id":{"type":"string","format":"uuid"},"folio":{"type":["integer","null"]},"tipo":{"type":["string","null"]},"tipo_documento":{"type":["string","null"]},"periodo":{"type":["string","null"],"pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"url":{"type":"string","description":"URL relativa autenticada para un artefacto directo o URL absoluta firmada para un PDF legacy. Si es relativa, conserva Authorization; si es absoluta, usa un request limpio."},"autenticacion":{"type":["string","null"],"enum":["api_key",null],"description":"api_key cuando la URL relativa exige la misma llave; ausente o null para la URL firmada legacy."},"expira_en":{"type":["string","null"],"format":"date-time","description":"Vencimiento UTC de una URL legacy; null para la descarga autenticada directa."},"vigencia_segundos":{"type":["integer","null"],"enum":[300,null],"description":"300 para la URL legacy; null para la descarga directa autenticada."}}},"meta":{"type":"object","required":["version"],"properties":{"version":{"type":"string","const":"v1"}}}}},"ValoresF29":{"type":"object","description":"Montos en pesos del formulario.","required":["debito_fiscal","credito_fiscal","iva_a_pagar","remanente_periodo","ppm","retencion_honorarios","impuesto_unico_trabajadores","total_a_pagar"],"properties":{"debito_fiscal":{"type":"number"},"credito_fiscal":{"type":"number"},"iva_a_pagar":{"type":"number"},"remanente_periodo":{"type":"number"},"ppm":{"type":"number"},"retencion_honorarios":{"type":"number"},"impuesto_unico_trabajadores":{"type":"number"},"total_a_pagar":{"type":"number"}}},"PeriodoF29":{"type":"object","required":["periodo","estado","folio_sii","es_provisorio","fuente","valores"],"properties":{"periodo":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"estado":{"type":"string","description":"Estado del formulario tal como lo registra el sistema."},"folio_sii":{"type":["string","null"],"description":"Folio del SII. Solo llega cuando el formulario está efectivamente declarado."},"es_provisorio":{"type":"boolean","description":"En true el número todavía no está declarado ante el SII y puede cambiar. Dilo siempre que lo cites."},"fuente":{"type":"string","enum":["sii_declarado","motor"],"description":"sii_declarado si el valor viene del SII, motor si lo calculó Ordis."},"valores":{"$ref":"#/components/schemas/ValoresF29"}}},"RespuestaF29":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PeriodoF29"}},"meta":{"type":"object","required":["periodo","fuente"],"properties":{"periodo":{"type":["string","null"]},"fuente":{"type":["string","null"],"description":"Solo llega cuando pediste un período. En el listado es null: cada elemento trae la suya."}}}}},"ValoresF22":{"type":"object","description":"Montos en pesos de la declaración.","required":["renta_liquida_imponible","idpc_neto","ppm","resultado_liquidacion","saldo_a_pagar","devolucion"],"properties":{"renta_liquida_imponible":{"type":"number"},"idpc_neto":{"type":"number"},"ppm":{"type":"number"},"resultado_liquidacion":{"type":"number","description":"Mayor que 0 paga, menor que 0 le devuelven, 0 cuando es indeterminado."},"saldo_a_pagar":{"type":"number"},"devolucion":{"type":"number"}}},"DeclaracionF22":{"type":"object","required":["anio_tributario","anio_declaracion","regimen","estado","folio_sii","es_provisorio","indeterminado","fuente","fecha_presentacion","fecha_pago","valores","resultado"],"properties":{"anio_tributario":{"type":"integer","description":"Ejercicio comercial. El AT 2025 se declara en 2026."},"anio_declaracion":{"type":["integer","null"]},"regimen":{"type":["string","null"],"description":"Régimen tributario del ejercicio."},"estado":{"type":"string"},"folio_sii":{"type":["string","null"]},"es_provisorio":{"type":"boolean"},"indeterminado":{"type":"boolean","description":"En true la declaración existe pero no se puede decidir con confianza si hay pago o devolución. Se debe mostrar sin valor, nunca $0."},"fuente":{"type":"string","enum":["sii_declarado","motor"]},"fecha_presentacion":{"type":["string","null"],"format":"date"},"fecha_pago":{"type":["string","null"],"format":"date"},"valores":{"$ref":"#/components/schemas/ValoresF22"},"resultado":{"type":"object","required":["tipo","monto"],"properties":{"tipo":{"type":"string","enum":["pagar","devolucion","neutro","indeterminado"]},"monto":{"type":"number","description":"0 cuando el tipo es neutro o indeterminado."}}}}},"RespuestaF22":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DeclaracionF22"}},"meta":{"type":"object","required":["anio","fuente"],"properties":{"anio":{"type":["integer","null"]},"fuente":{"type":["string","null"]}}}}},"LineaDesgloseF29":{"type":"object","required":["etiqueta","codigoSii","monto","signo"],"properties":{"etiqueta":{"type":"string"},"codigoSii":{"type":["integer","null"],"description":"Código del formulario 29. null en las líneas de resultado."},"monto":{"type":"number"},"signo":{"type":"string","enum":["+","-","="]},"esSubtotal":{"type":"boolean","description":"Subtotal intermedio, no el total final."}}},"KpiResumen":{"type":"object","required":["total","explicacion","documentos"],"properties":{"total":{"type":"number","description":"Monto en pesos. Reconcilia exacto con el mismo indicador del portal."},"explicacion":{"type":"string","description":"Cómo se compone el total, en lenguaje claro."},"documentos":{"type":"integer","description":"Cuántos documentos lo componen."},"es_provisorio":{"type":"boolean","description":"Solo en el indicador f29: el formulario todavía no está declarado."},"desglose":{"type":"array","items":{"$ref":"#/components/schemas/LineaDesgloseF29"},"description":"Solo en el indicador f29: apertura por código tributario."},"sin_datos":{"type":"string","description":"Aparece en lugar del desglose cuando el indicador no tiene con qué calcularse."}}},"RespuestaKpis":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["ventas","gastos","f29","resultado"],"properties":{"ventas":{"$ref":"#/components/schemas/KpiResumen"},"gastos":{"$ref":"#/components/schemas/KpiResumen"},"f29":{"$ref":"#/components/schemas/KpiResumen"},"resultado":{"$ref":"#/components/schemas/KpiResumen"}}},"meta":{"type":"object","required":["periodo","modo","base"],"properties":{"periodo":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"modo":{"type":"string","enum":["en_curso","cerrado"],"description":"en_curso acumula hasta hoy en Chile; cerrado cubre el mes completo."},"base":{"type":"string","const":"p1"}}}}},"FilaFCF":{"type":"object","description":"Una línea del flujo de caja, con sus 12 meses.","required":["id","label","grupo","valores","total"],"properties":{"id":{"type":"string"},"label":{"type":"string","description":"Nombre visible de la línea."},"grupo":{"type":"string","enum":["saldo","ingresos_venta","costos","gav","intereses","otros_ingresos","obligaciones","financiamiento","resultado","informativa"]},"valores":{"type":"array","minItems":12,"maxItems":12,"items":{"type":["number","null"]},"description":"Un valor por mes; el índice 0 es enero. null significa que no aplica (por ejemplo, saldo sin cartola)."},"total":{"type":["number","null"],"description":"Suma del año. null en las filas de saldo."},"esTotal":{"type":"boolean"},"esInformativa":{"type":"boolean","description":"Línea gris: no suma al flujo."},"porCategorizar":{"type":"boolean","description":"Contiene montos que todavía no están categorizados."}}},"MesFCF":{"type":"object","required":["periodo","modo","esMesEnCurso"],"properties":{"periodo":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"modo":{"type":"string","enum":["caja","estimado","proyectado"],"description":"caja es movimiento bancario real, estimado usa documentos, proyectado es a futuro."},"esMesEnCurso":{"type":"boolean"}}},"SeccionFlujoCaja":{"type":"object","required":["id","titulo","subtitulo","filas","subtotal"],"properties":{"id":{"type":"string","enum":["ingresos","egresos","costos_financieros","impuestos","financiamiento"]},"titulo":{"type":"string"},"subtitulo":{"type":"string"},"filas":{"type":"array","items":{"$ref":"#/components/schemas/FilaFCF"}},"subtotal":{"$ref":"#/components/schemas/FilaFCF"}}},"RespuestaFlujoCaja":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["anio","meses","saldoInicial","secciones","flujoNeto","flujoAcumulado","saldoFinal","informativas","tieneCartolas","datosIncompletos"],"properties":{"anio":{"type":"integer"},"meses":{"type":"array","items":{"$ref":"#/components/schemas/MesFCF"}},"saldoInicial":{"oneOf":[{"$ref":"#/components/schemas/FilaFCF"},{"type":"null"}]},"secciones":{"type":"array","items":{"$ref":"#/components/schemas/SeccionFlujoCaja"},"description":"En orden de caja. Se omiten las secciones sin filas."},"flujoNeto":{"$ref":"#/components/schemas/FilaFCF"},"flujoAcumulado":{"oneOf":[{"$ref":"#/components/schemas/FilaFCF"},{"type":"null"}]},"saldoFinal":{"oneOf":[{"$ref":"#/components/schemas/FilaFCF"},{"type":"null"}]},"informativas":{"type":"array","items":{"$ref":"#/components/schemas/FilaFCF"}},"tieneCartolas":{"type":"boolean"},"datosIncompletos":{"type":"boolean","description":"Viaja siempre, también en false. En true el cálculo alcanzó un tope de filas y los totales salen menores que la realidad: no trates el resultado como definitivo."}}},"meta":{"type":"object","required":["anio","base"],"properties":{"anio":{"type":"integer"},"base":{"type":"string","const":"fcf-operacional"}}}}},"Liquidacion":{"type":"object","required":["periodo","trabajador","sueldo_base","total_haberes","total_descuentos","sueldo_liquido","costo_empleador"],"properties":{"periodo":{"type":["string","null"],"pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"trabajador":{"type":"object","required":["rut","nombre"],"properties":{"rut":{"type":["string","null"]},"nombre":{"type":["string","null"]}}},"sueldo_base":{"type":"number"},"total_haberes":{"type":"number"},"total_descuentos":{"type":"number"},"sueldo_liquido":{"type":"number","description":"Lo que recibe el trabajador."},"costo_empleador":{"type":"number","description":"Lo que le cuesta a la empresa: haberes más los aportes de cargo del empleador."}}},"RespuestaLiquidaciones":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Liquidacion"}},"meta":{"type":"object","required":["periodo","periodos"],"properties":{"periodo":{"type":["string","null"]},"periodos":{"type":"array","items":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"description":"Períodos incluidos en esta respuesta."}}}}},"Trabajador":{"type":"object","required":["rut","nombre","cargo","fecha_ingreso","fecha_termino","estado","tipo_contrato","tipo_jornada","horas_semanales","sueldo_base"],"properties":{"rut":{"type":"string"},"nombre":{"type":"string"},"cargo":{"type":["string","null"]},"fecha_ingreso":{"type":["string","null"],"format":"date"},"fecha_termino":{"type":["string","null"],"format":"date"},"estado":{"type":"string","description":"activo, licencia, vacaciones o desvinculado."},"tipo_contrato":{"type":["string","null"]},"tipo_jornada":{"type":["string","null"]},"horas_semanales":{"type":["number","null"]},"sueldo_base":{"type":"number","description":"Sueldo base contratado. No incluye gratificación, horas extra, bonos ni aportes del empleador."}}},"RespuestaTrabajadores":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Trabajador"}},"meta":{"type":"object","required":["estado","limit","has_more"],"properties":{"estado":{"type":["string","null"]},"limit":{"type":"integer","const":500},"has_more":{"type":"boolean"}}}}},"BoletaHonorarios":{"type":"object","required":["folio","fecha","rut_emisor","nombre_emisor","monto_bruto","retencion","monto_liquido","periodo","estado"],"properties":{"folio":{"type":["integer","null"],"description":"Folio por emisor: dos prestadores distintos pueden compartirlo."},"fecha":{"type":["string","null"],"format":"date"},"rut_emisor":{"type":["string","null"]},"nombre_emisor":{"type":["string","null"]},"monto_bruto":{"type":"number"},"retencion":{"type":"number","description":"Solo las boletas vigente cuentan para la retención."},"monto_liquido":{"type":"number"},"periodo":{"type":["string","null"],"pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"estado":{"type":["string","null"],"description":"vigente, anulada o rechazada."}}},"RespuestaBoletasHonorarios":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BoletaHonorarios"}},"meta":{"type":"object","required":["periodo","estado","page","limit","has_more"],"properties":{"periodo":{"type":["string","null"]},"estado":{"type":["string","null"]},"page":{"type":"integer"},"limit":{"type":"integer","const":200},"has_more":{"type":"boolean"}}}}},"MovimientoBanco":{"type":"object","required":["fecha","descripcion","referencia","monto","saldo","tipo","periodo","estado_conciliacion","conciliado","categoria","categoria_nombre","categoria_fcf"],"properties":{"fecha":{"type":["string","null"],"format":"date"},"descripcion":{"type":["string","null"]},"referencia":{"type":["string","null"]},"monto":{"type":"number","description":"Positivo es abono (entró plata), negativo es cargo (salió)."},"saldo":{"type":["number","null"],"description":"Saldo de la cuenta después del movimiento, si la cartola lo trae."},"tipo":{"type":"string","enum":["cargo","abono"]},"periodo":{"type":["string","null"],"pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"estado_conciliacion":{"type":["string","null"],"description":"Estado tal como lo registra el sistema (por ejemplo conciliado o propuesto)."},"conciliado":{"type":"boolean","description":"true solo cuando el estado es conciliado. Un match propuesto y no confirmado no cuenta: contarlo haría creer que la cartola está cuadrada cuando no lo está."},"categoria":{"type":["string","null"],"description":"Código de la categoría de conciliación."},"categoria_nombre":{"type":["string","null"]},"categoria_fcf":{"type":["string","null"],"description":"Clasificación del flujo de caja. Es distinta de categoria."}}},"RespuestaMovimientosBanco":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MovimientoBanco"}},"meta":{"type":"object","required":["periodo","page","limit","has_more"],"properties":{"periodo":{"type":["string","null"]},"page":{"type":"integer"},"limit":{"type":"integer","const":200},"has_more":{"type":"boolean"}}}}},"CuotaDeuda":{"type":"object","required":["numero","fecha_vencimiento","monto_total","monto_capital","monto_interes","estado"],"properties":{"numero":{"type":"integer"},"fecha_vencimiento":{"type":"string","format":"date"},"monto_total":{"type":"number"},"monto_capital":{"type":"number"},"monto_interes":{"type":"number"},"estado":{"type":"string"}}},"Deuda":{"type":"object","required":["id","tipo","naturaleza","descripcion","acreedor","monto_original","saldo_actual","moneda","estado","numero_cuotas_total","cuota_mensual","tasa_interes_anual","fecha_primera_cuota","dia_pago_mes","cuotas_pendientes","monto_pendiente","proxima_cuota"],"properties":{"id":{"type":"string","format":"uuid"},"tipo":{"type":"string","description":"Instrumento (por ejemplo credito_bancario o leasing)."},"naturaleza":{"type":"string","enum":["pasivo","activo"],"description":"pasivo significa que la empresa debe; activo, que le deben. Es este campo el que define la dirección, no tipo."},"descripcion":{"type":"string"},"acreedor":{"type":"string"},"monto_original":{"type":"number"},"saldo_actual":{"type":"number"},"moneda":{"type":"string","description":"Por defecto CLP."},"estado":{"type":"string","description":"activo, pagado o cancelado."},"numero_cuotas_total":{"type":["integer","null"]},"cuota_mensual":{"type":["number","null"]},"tasa_interes_anual":{"type":["number","null"],"description":"En porcentaje anual."},"fecha_primera_cuota":{"type":["string","null"],"format":"date"},"dia_pago_mes":{"type":["integer","null"]},"cuotas_pendientes":{"type":"integer","description":"Cuotas con estado distinto de pagada (pendiente, vencida y parcial). 0 cuando no hay cronograma."},"monto_pendiente":{"type":"number"},"proxima_cuota":{"oneOf":[{"$ref":"#/components/schemas/CuotaDeuda"},{"type":"null"}],"description":"null cuando no hay cronograma, como en una tarjeta rotativa."}}},"RespuestaDeudas":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Deuda"}},"meta":{"type":"object","required":["estado","limit","has_more"],"properties":{"estado":{"type":["string","null"]},"limit":{"type":"integer","const":200},"has_more":{"type":"boolean"}}}}},"EstadoServicio":{"type":"object","required":["status","supabase","timestamp","version","environment"],"properties":{"status":{"type":"string","enum":["healthy","degraded"]},"supabase":{"type":"boolean","description":"Si la base de datos respondió."},"timestamp":{"type":"string","format":"date-time"},"version":{"type":"string","description":"Identificador corto del despliegue."},"environment":{"type":"string","description":"Ambiente que respondió."}}},"Indicadores":{"type":"object","required":["uf","uf_fecha","utm","utm_fecha","dolar","dolar_fecha","fuente","cache_age_ms"],"properties":{"uf":{"type":"number","description":"Valor de la UF en pesos."},"uf_fecha":{"type":"string"},"utm":{"type":"number","description":"Valor de la UTM en pesos."},"utm_fecha":{"type":"string"},"dolar":{"type":"number","description":"Dólar observado en pesos. 0 cuando la fuente es fallback."},"dolar_fecha":{"type":"string"},"fuente":{"type":"string","enum":["api","cache","fallback"]},"cache_age_ms":{"type":"integer","description":"Antigüedad del valor en milisegundos. -1 cuando la fuente es fallback."}}}}}}