Cairos
Facturación
Programa de facturaciónPresupuestosFacturas recurrentesGastos y proveedoresCobros y tesorería
Contabilidad e impuestos
ContabilidadModelos de HaciendaLibros registroInmovilizadoIGIC y Canarias
Operaciones
Inventario y almacenesCRMControl horarioProyectosSubvenciones y ayudas
Cumplimiento
VeriFactuTicketBAIFactura electrónicaToda la normativaSeguridad y datos
Por tipo de negocio
AutónomosPymesAsesorías y gestoríasExtranjeros en EspañaStartupsComercios y tiendas
Por sector
Hostelería y restaurantesConstrucción y reformasServicios profesionalesComercio electrónicoTodos los sectores
Por forma jurídica
AsociacionesFundacionesCooperativasClubes deportivosTodas las formas jurídicas
Cambiar de programa
ComparativasAlternativa a HoldedMigrar tus datos
Herramientas gratis
Plantilla de facturaCalculadora de IVACalculadora de IRPFTodas las herramientas
Aprender
GuíasGlosarioCalendario fiscalBlog
Desarrolladores
API y documentaciónEmpezar en cinco minutosReferencia de recursosWebhooks
Ayuda
Centro de ayudaContacto
Precios
Empieza gratis Iniciar sesión
Autenticación

Una cabecera, dos clases de clave y diez permisos

Todo lo que hay que entender de la seguridad de esta API cabe en tres ideas: la clave va en Authorization, la de pruebas trabaja sobre tus datos de verdad, y un permiso de escritura no te deja leer.

Bearer sobre HTTPSLa clave se enseña una vezDiez scopes

La API está en marcha. Esto es lo que hay hoy y lo que no

Funciona. Las rutas de esta documentación están desplegadas y respondiendo en https://erp.cairos.es/api/v1/. Los ejemplos de estas páginas se pueden copiar y ejecutar. La especificación completa está en openapi.json, que es lo que importan Make y n8n.

Las claves te las creas tú, desde Desarrolladores en tu cuenta de Cairos. Empieza con una cai_test_: trabaja contra tus datos de verdad pero no registra en VeriFactu ni envía correos, así que puedes montar tu integración sin ensuciar una serie de facturación.

Y lo que todavía NO hay, dicho sin adornos: ningún conector oficial. Ni app de Shopify, ni plugin de WooCommerce, ni módulo publicado en Make o n8n. Con la API y su especificación se pueden construir —para eso están las guías de esta sección— pero construirlos es trabajo, y ese trabajo no está hecho.

Si montas algo con esto, escríbenos a hola@cairos.es. Nos interesa especialmente lo que te falte del contrato: es lo que decide qué se amplía primero.

La cabecera, y nada más

Toda llamada lleva la clave en Authorization, con la palabra Bearer delante y un espacio en medio. No hay cookies, no hay OAuth, no hay sesión que caduque y no hay que firmar la petición.

Cabeceras
Authorization: Bearer cai_live_TU_CLAVE
Content-Type: application/json
Idempotency-Key: pedido-1042

Sólo HTTPS. Una llamada por HTTP no se redirige a HTTPS: se rechaza. Redirigirla parece más amable y significaría que la clave ha viajado ya una vez en claro, que es exactamente lo que no puede pasar.

cai_test_ y cai_live_: la diferencia no es la que esperas

Hay dos clases de clave y se distinguen por el prefijo. Lo que las separa no es que trabajen contra bases de datos distintas:

cai_test_cai_live_
Sobre qué datos trabajaLos tuyos, los mismosLos tuyos
Crea facturas de verdadSí, con su número de serie
Registra en VeriFactuNo
Envía correosNo
Para qué sirveDesarrollar sin ensuciar una serie de facturación de verdadProducción

Dicho de otro modo: la clave de pruebas no es un patio de recreo aislado. Es la clave normal con las dos consecuencias irreversibles apagadas.

Por qué se ha hecho así. Un entorno de pruebas separado obliga a mantener dos copias de tu empresa y a que nunca se parezcan del todo: en el de pruebas no están tus clientes reales, ni tus series, ni tus tipos de IVA, y la integración que funcionaba allí falla el primer día en producción. Aquí desarrollas contra tus datos de verdad, que es donde vas a acabar, y lo único que no ocurre es lo que no se puede deshacer: el registro en la Agencia Tributaria y el correo al cliente.

Y la contrapartida, dicha claramente: lo que crees con una clave de pruebas aparece en tu cuenta y consume numeración de serie si emites. Si vas a lanzar un bucle de doscientas facturas, usa una serie aparte para pruebas.

La clave se enseña una vez y no la guardamos

Al crearla se enseña entera, una vez. De ahí en adelante sólo se ve su huella y los últimos caracteres, lo justo para reconocer cuál es cuál en una lista.

No es una molestia de diseño: no tenemos la clave. Se guarda su huella, con la que se puede comprobar que la que llega es la buena, pero de la que no se puede reconstruir la original. Si un día alguien se lleva nuestra base de datos, no se lleva tus claves.

Las consecuencias son dos, y las dos son tuyas:

  • Si la pierdes, no te la podemos recuperar. Se revoca y se crea otra.
  • Si se filtra, revócala tú. Revocar es inmediato y no rompe nada de lo ya creado: las facturas que hizo esa clave siguen ahí.

Dónde no va una clave

No va en el código fuente, ni en el repositorio, ni en el JavaScript de una página web, ni en una aplicación móvil, ni en una captura de pantalla de una incidencia. Todo eso es publicarla. Va en una variable de entorno del servidor o en el gestor de secretos que uses.

Los diez scopes, y la trampa que tienen

Cada clave lleva la lista de lo que puede hacer. Se eligen al crearla y no se amplían solas.

Un scope de escritura no incluye el de lectura

Es la única regla contraintuitiva de todo esto y provoca el 403 más repetido. Una clave con invoices:write puede crear una factura y no puede leerla. Si tu integración crea y luego consulta —que es lo normal— necesita los dos: invoices:read y invoices:write.

ScopeQué abreRecurso
contacts:readLeer contactos: clientes, proveedores y sus datos fiscales./contactos
contacts:writeCrear y modificar contactos./contactos
products:readLeer el catálogo de productos y servicios./productos
products:writeCrear y modificar productos./productos
invoices:readLeer facturas de venta, sus líneas y su estado./facturas
invoices:writeCrear facturas, modificar borradores y emitir./facturas
expenses:readLeer gastos y facturas de proveedor./gastos
expenses:writeCrear y modificar gastos./gastos
payments:readLeer cobros y su asignación a facturas./cobros
payments:writeRegistrar cobros./cobros
webhooks:manageCrear, listar y borrar suscripciones a sucesos./webhooks

GET /organizacion no pide ninguno: si la clave es válida, responde. Es la llamada con la que conviene comprobar que la autenticación funciona antes de pelearse con los permisos.

Cómo elegirlos. Da el mínimo que hace falta y da el mínimo de verdad, no «los de facturas por si acaso». Tres casos que cubren casi todo:

Lo que estás montandoLo que necesita
Una tienda que factura solacontacts:read contacts:write invoices:read invoices:write payments:write
Un panel que sólo enseña datosinvoices:read expenses:read payments:read
Una asesoría que descarga los libros de un clienteinvoices:read expenses:read contacts:read

Fíjate en el tercero: sin un solo permiso de escritura, esa clave no puede estropear nada aunque el código que la usa tenga un fallo. Ése es todo el sentido de que existan los scopes.

401 y 403 no son lo mismo, y decirlo ahorra una tarde

Se confunden todo el rato y significan cosas muy distintas:

CódigoQué diceQué hacer
401 no_autenticadoNo sé quién eres. No ha llegado clave, o la que ha llegado no vale, o está revocada.Revisa la cabecera. Reintentar no sirve de nada: va a fallar igual.
403 sin_permisoSé quién eres y no puedes. La clave es buena; le falta el scope de esa operación.Mira error.detalles, que dice qué scope faltaba, y crea una clave con él.

La regla para acordarse: el 401 se arregla con una clave distinta; el 403, con una clave mejor.

Rotar, revocar y sobrevivir a las dos cosas

Una clave no caduca sola. Aun así conviene cambiarla de vez en cuando, y hay un día en que no queda más remedio: cuando se ha filtrado.

La forma de hacerlo sin cortar el servicio es la de siempre y no tiene misterio: crear la nueva, ponerla en producción, comprobar que funciona y sólo entonces revocar la vieja. Como las claves no se pueden leer después de creadas, el orden importa: si revocas primero y la nueva no estaba bien puesta, te quedas sin las dos.

Y una recomendación que se agradece a los seis meses: una clave por integración, no una para todo. Cuando algo falle vas a querer saber qué sistema lo hizo, y cuando algo se filtre vas a querer revocar sólo eso.

Lo que hacemos nosotros con esto

Guardar bien tus claves es la mitad del trabajo; la otra mitad es nuestra. Las claves se guardan como huella y no en claro, cada organización está aislada de las demás y los servidores y las copias están en la Unión Europea. Lo que todavía no tenemos —doble factor, ver y cerrar sesiones abiertas, certificaciones— está escrito sin adornos en seguridad y datos, incluida la lista de lo que falta.

Si encuentras un fallo de seguridad en la API, escríbenos a hola@cairos.es con el asunto «Seguridad» antes de contarlo en ningún otro sitio.

Preguntas sobre claves y permisos

No caduca sola. Vale hasta que la revocas. Aun así conviene rotarla de vez en cuando y, sobre todo, tener una clave distinta por integración para poder revocar sólo la que se ha filtrado.
No. No la guardamos: guardamos su huella, que sirve para comprobar la que llega pero no para reconstruirla. Si la pierdes, se revoca esa y se crea otra.
No. Es la regla que más sorprende: un scope de escritura no implica el de lectura. Si tu integración crea una factura y después la consulta, necesita invoices:write y invoices:read.
No. Las claves se emiten contra una organización. Una asesoría con diez clientes acaba con diez claves, y eso es deliberado: es lo que impide que un fallo en tu código escriba en la contabilidad de otro. Más en asesorías.
Hoy no. Sólo hay claves que crea el titular de la cuenta y te entrega. Si estás construyendo una aplicación para varios clientes de Cairos, escríbenos: es la petición que decidiría si merece la pena montarlo, y todavía no está.
El 401 dice «no sé quién eres» y se arregla con otra clave. El 403 dice «sé quién eres y no puedes» y se arregla con una clave que tenga el scope que falta.

Pide una clave de pruebas y monta la primera llamada

Con el mínimo de scopes que necesites. Ampliarlos después es una clave nueva, y eso es rápido.

Sólo HTTPS · Clave por integración · Revocar es inmediato

Soporte