Cairos
Facturación
Programa de facturaciónOrzamentosFacturas recorrentesGastos e provedoresCobros e tesouraría
Contabilidade e impostos
ContabilidadeModelos de FacendaLibros rexistroInmobilizadoIGIC e Canarias
Operacións
Inventario e almacénsCRMControl horarioProxectosSubvencións e axudas
Cumprimento
VeriFactuTicketBAIFactura electrónicaToda a normativaSeguridade e datos
Por tipo de negocio
AutónomosPemesAsesorías e xestoríasEstranxeiros en EspañaStartupsComercios e tendas
Por sector
Hostalaría e restaurantesConstrución e reformasServizos profesionaisComercio electrónicoTodos os sectores
Por forma xurídica
AsociaciónsFundaciónsCooperativasClubs deportivosTodas as formas xurídicas
Cambiar de programa
ComparativasAlternativa a HoldedMigrar os teus datos
Ferramentas gratis
Modelo de facturaCalculadora de IVECalculadora de IRPFTodas as ferramentas
Aprender
GuíasGlosarioCalendario fiscalBlog
Desenvolvedores
API e documentaciónComezar en cinco minutosReferencia de recursosWebhooks
Axuda
Centro de axudaContacto
Prezos
Comeza gratis Iniciar sesión
Primeiros pasos

De cero a unha factura emitida, en seis chamadas

Sen SDK, sen instalar nada e sen ler a referencia enteira. Seis chamadas que podes copiar, pegar e executar agora mesmo: a API está despregada e a clave créala ti desde a túa conta. Comeza cunha de probas e non enlixarás ningunha serie de facturación.

curl, JavaScript e PHPSen dependenciasCopiar e pegar

A API está en marcha. Isto é o que hai hoxe e o que non

Funciona. As rutas desta documentación están despregadas e respondendo en https://erp.cairos.es/api/v1/. Os exemplos destas páxinas pódense copiar e executar. A especificación completa está en openapi.json, que é o que importan Make e n8n.

As claves créalas ti, desde Desenvolvedores na túa conta de Cairos. Comeza cunha cai_test_: traballa contra os teus datos de verdade pero non rexistra en VeriFactu nin envía correos, así que podes montar a túa integración sen enlixar unha serie de facturación.

E o que aínda NON hai, dito sen adornos: ningún conector oficial. Nin app de Shopify, nin plugin de WooCommerce, nin módulo publicado en Make ou n8n. Coa API e a súa especificación pódense construír —para iso están as guías desta sección— pero construílos é traballo, e ese traballo non está feito.

Se montas algo con isto, escríbenos a hola@cairos.es. Interésanos especialmente o que che falte do contrato: é o que decide que se amplía primeiro.

O percorrido

O que vas facer

Tres bloques. O primeiro faise na túa conta, nun minuto; os outros dous son código.

1

Crear a clave

En Desenvolvedores, dentro da túa conta. Comeza por unha de probas, e apúntaa: amósase unha soa vez.

2

Comprobar que chega

Unha chamada a /organizacion, que non pide ningún permiso. Se responde, o resto é costa abaixo.

3

Facturar

Contacto, factura en borrador, emisión e PDF. Catro chamadas máis e xa está feito.

1 · Crea a clave

Na túa conta de Cairos, en Desenvolvedores. Non hai que pedila por correo nin agardar a que ninguén conteste: escolles o modo, marcas os permisos un a un e xérase no momento. Comeza cunha de probas, que empeza por cai_test_.

Marca os permisos que vas usar nesta páxina e ningún máis: contacts:write para o paso 3, e invoices:read e invoices:write para os pasos 4, 5 e 6. Se che falta un, o erro dío polo seu nome e arránxase creando outra clave.

A clave amósase unha soa vez. Non a gardamos: gardamos a súa pegada, que serve para recoñecela pero non para reconstruíla. Se a perdes non cha podemos recuperar; hai que revogala e crear outra. Gárdaa onde gardes os contrasinais do teu servidor —unha variable de contorno, un xestor de segredos— e non no código.

Que fai distinta a clave de probas

Traballa contra os mesmos datos ca a de produción: o que crees con ela aparece na túa conta. O que non fai é rexistrar en VeriFactu nin enviar correos. Iso é exactamente o que che permite desenvolver sen enlixar unha serie de facturación de verdade. Non é unha copia da túa empresa nun servidor aparte, e convén telo claro antes de lanzar un bucle de probas.

2 · A primeira chamada, que confirma que todo está ben

GET /organizacion devolve os datos fiscais da túa empresa. É a chamada máis barata que hai e non pide ningún scope: se a túa clave vale, responde.

export CAIROS_CLAVE=cai_test_TU_CLAVE

curl https://erp.cairos.es/api/v1/organizacion \
  -H "Authorization: Bearer $CAIROS_CLAVE"

Cando saia un 200 co nome da túa empresa dentro, terás rematado a parte difícil.

200 OK
{
  "id": "clx3k2p9y0000qz8h1a2b3c4d",
  "nombre": "Talleres Miralles SL",
  "razon_social": "Talleres Miralles, S.L.",
  "nif": "B12345674",
  "ciudad": "Girona",
  "provincia": "Girona",
  "moneda": "EUR",
  "region_fiscal": "peninsula",
  "tipo_iva_defecto": 21,
  "recargo_equivalencia": false,
  "plan_contable": "pgc"
}

Os identificadores son así de feos a propósito: son cuid, opacos e sen prefixo. Non os interpretes nin intentes deducir de que recurso son —gárdaos tal cal e mándaos onde toque—, porque o día que deixen de ter esta forma o teu código non debería enterarse.

E se sae un 401, a clave non chegou ben. Os dous motivos son case sempre o mesmo: falta a palabra Bearer diante, ou a variable de contorno está baleira e estás mandando a cabeceira sen nada detrás.

3 · Crea un contacto

Unha factura necesita a quen lla fas. Con contacts:write:

curl -X POST https://erp.cairos.es/api/v1/contactos \
  -H "Authorization: Bearer $CAIROS_CLAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: alta-cliente-1042" \
  -d '{
    "nombre": "Grupo Bonaire SL",
    "nif": "B17654321",
    "email": "admin@bonaire.example",
    "tipo": "customer"
  }'

Volve un 201 co contacto creado e o seu id. Gárdao: é o que vai pedir a factura.

Fíxate na cabeceira Idempotency-Key. Aquí aínda non doe —un contacto duplicado bórrase— pero é o mesmo hábito que dentro de dous pasos evita que emitas dúas facturas do mesmo pedido. Está contado enteiro en idempotencia.

4 · Crea a factura, que nace en borrador

Con invoices:write. A factura créase sen número e en estado borrador:

curl -X POST https://erp.cairos.es/api/v1/facturas \
  -H "Authorization: Bearer $CAIROS_CLAVE" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: pedido-1042" \
  -d '{
    "contacto_id": "clx3k2p9y0000qz8h1a2b3c4d",
    "serie": "F27",
    "fecha_emision": "2027-03-02",
    "lineas": [
      {
        "descripcion": "Revision anual",
        "cantidad": 2,
        "precio": 180.00,
        "tipo_iva": 21
      }
    ]
  }'
201 Created
{
  "id": "clx3k2p9y0001qz8h5e6f7g8h",
  "serie": "F27",
  "numero": null,
  "referencia": null,
  "tipo_documento": "invoice",
  "estado": "draft",
  "fecha_emision": "2027-03-02",
  "fecha_vencimiento": null,
  "base_imponible": 360.00,
  "cuota_iva": 75.60,
  "cuota_irpf": 0.00,
  "total": 435.60,
  "cobrado": 0.00,
  "pendiente": 435.60
}

numero e referencia veñen a null, e iso é correcto: o número non existe ata que se emite. Os totais, en cambio, xa veñen calculados, así que aquí é onde se comproba que o que mandaches cadra co que esperabas cobrar.

Fíxate en estado: vale draft, en inglés. Os recursos e os campos desta API están en castelán, pero uns cantos valores de enumerado quedaron en inglés —draft, sent, paid, overdue— e aí quedan, porque traducilos rompería toda integración escrita ata hoxe.

5 · Emítea, que é o paso que non se desfai

Agora si. Ao emitir, a factura toma o seguinte número da súa serie e xérase o rexistro de VeriFactu encadeado co anterior.

curl -X POST \
  https://erp.cairos.es/api/v1/facturas/clx3k2p9y0001qz8h5e6f7g8h/emitir \
  -H "Authorization: Bearer $CAIROS_CLAVE" \
  -H "Idempotency-Key: emitir-pedido-1042"
201 Created
{
  "id": "clx3k2p9y0001qz8h5e6f7g8h",
  "serie": "F27",
  "numero": 42,
  "referencia": "F27-0042",
  "estado": "sent",
  "total": 435.60,
  "pendiente": 435.60,
  "verifactu": {
    "registrada": true,
    "huella": "7f3c1a…d904",
    "registrada_en": "2027-03-02T10:41:08.517Z",
    "aeat": null
  }
}

Dúas cousas desa resposta que convén mirar ben. numero é un enteiro, non un texto: o «F27-0042» que se amosa impreso é referencia, que xunta serie e número. E o estado pasa a sent, que é o mesmo en que a deixa o botón «Marcar enviada» da pantalla.

Se volves chamar a /emitir sobre unha factura xa emitida, non sae un erro: sae a mesma factura co seu mesmo número, e un 200 en vez do 201. É a propósito, e é o que permite reintentar sen arriscar un salto na numeración cando non sabes se a primeira chamada chegou.

Cunha clave de probas, «verifactu» vén con registrada: false

O bloque chega igual —non desaparece—, pero di a verdade: unha clave cai_test_ non rexistra en VeriFactu nin manda correos, así que huella e registrada_en veñen a null. Todo o demais —o número da serie, os totais, o PDF— funciona igual. E ese campo é xusto o que hai que mirar o día que pases a produción, para comprobar que agora si se rexistra.

6 · E descarga o PDF

GET /facturas/{id}/pdf non devolve JSON: devolve o ficheiro, co seu código QR e a súa lenda xa impresos.

curl
curl https://erp.cairos.es/api/v1/facturas/clx3k2p9y0001qz8h5e6f7g8h/pdf \
  -H "Authorization: Bearer $CAIROS_CLAVE" \
  -o factura.pdf

E xa está: seis chamadas, e ao final unha factura emitida, numerada e en PDF. O resto da documentación é detalle sobre isto.

O que falla nos dous primeiros minutos

Case sempre é unha destas cinco cousas, e ningunha é interesante. Por iso paga a pena telas xuntas:

O que vesO que pasa de verdade
401 no_autenticadoFalta a palabra Bearer diante da clave, ou a variable de contorno está baleira e mandas a cabeceira con nada dentro. Comproba o segundo antes de dar por perdida a clave.
403 sin_permisoA clave é válida pero fáltalle o scope desa chamada. E ollo coa trampa: ter invoices:write non che deixa ler facturas. Son dous permisos distintos.
422 datos_invalidosO JSON chegou, pero algo dentro non vale. error.detalles dicho que campo e por que; mírao antes de tocar nada.
409 conflictoEstás intentando algo que o estado do documento non permite: emitir unha factura xa emitida, ou reutilizar unha Idempotency-Key cun corpo distinto.
O servidor non responde JSONAdoita ser o Content-Type. Se mandas corpo, ten que ir application/json: sen el, o corpo chega e non se le.

Os sete códigos de erro, co que hai que facer con cada un, están en erros e límites.

E agora, por onde sigo?

Depende do que esteas montando, e sinceramente só hai tres camiños:

  • Vas crear facturas desde outro sistema. Le idempotencia antes ca nada. É a páxina máis aburrida desta sección e a que evita o único erro desta API que non se arranxa borrando.
  • Necesitas enterarte do que pasa en Cairos. Entón o teu son os webhooks, non consultar a API cada cinco minutos.
  • Vas ler datos e pouco máis. Mira a paxinación por cursor, porque unha lista de facturas dun ano non cabe nunha resposta.

E se o que tes diante é unha tenda ou unha ferramenta de automatización, hai páxina propia: WooCommerce, Shopify, Make e n8n.

Dúbidas do primeiro día

Non. A clave emítese contra unha organización, así que fai falta unha conta —o plan gratuíto serve—. A clave créala ti desde Desenvolvedores; non hai que pedila nin agardar a que ninguén conteste.
Porque emitir é irreversible: asigna o número correlativo da serie e xera o rexistro de VeriFactu. Separalo en dúas chamadas déixache comprobar os totais antes de que ocorra o que xa non se pode desfacer. Se queres as dúas cousas seguidas, encadea as dúas chamadas; o que non facemos é quitarche a oportunidade de mirar.
Unha factura emitida non se borra: rectifícase, cunha factura rectificativa que deixa constancia. É o que esixe o regulamento de facturación, e por iso non hai un DELETE que o arranxe. Está explicado en VeriFactu.
Por defecto non: precio é o prezo unitario sen impostos e tipo_iva é o tipo en porcentaxe. A resposta trae base_imponible, cuota_iva e total xa calculados, que é o que convén comparar co que esperabas. Se vés dunha tenda ao público, onde o prezo que existe é o da etiqueta, manda precios_con_iva: true e Cairos detalla a base cara a atrás en céntimos enteiros, co mesmo motor que usa o conector de tendas.
Non o fagas. Poñer unha clave de API no JavaScript dunha páxina é publicala: calquera que abra as ferramentas do navegador ve a clave. As chamadas fanse desde o teu servidor, e o navegador fala co teu servidor, non con Cairos.

Seis chamadas, quince minutos con calma

Crea a clave de probas, pega o primeiro curl e segue ata o PDF. E se montas algo con isto, cóntanolo: o que lle falta á xente do contrato é o que decide que se amplía primeiro.

Clave de probas · Mesmos datos, sen VeriFactu nin correos

Soporte