API pública v1

Integra la facturación Veri*Factu de tus clientes con una API REST.

Contactos, productos, series y facturas — la misma lógica que usa la app de Kullqi, disponible por HTTP con clave de API. La cadena de registro y el envío a la AEAT se aplican igual, la llames desde donde la llames.

Crear un contactocURL
# sustituye sk_live_... por tu propia clave, generada en app.kullqi.com/api-keys
curl -X POST https://api.kullqi.com/v1/contacts \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "CUSTOMER",
    "legalName": "Comercial Ejemplo SL",
    "taxId": "B12345674",
    "email": "facturacion@ejemplo.com"
  }'

# respuesta — 201 Created
{
  "id": 42,
  "type": "CUSTOMER",
  "legalName": "Comercial Ejemplo SL",
  "taxId": "B12345674",
  "archived": false
}
Empieza aquí

Autenticación

Cada petición a /v1/** lleva tu clave en la cabecera Authorization, como token Bearer. Genera y revoca claves desde Claves de API en tu cuenta — solo un ADMIN puede hacerlo, y la clave se muestra una única vez al crearla (guárdala entonces; Kullqi solo conserva su hash, nunca el valor).

CabeceraHTTP
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Cada clave lleva uno o varios scopes — permisos por recurso, independientes del rol del usuario que la creó. Una petición a un endpoint sin el scope necesario recibe 403 Forbidden.

ScopePermite
contacts:readLeer y listar contactos.
contacts:writeCrear, modificar y archivar contactos.
products:readLeer y listar productos del catálogo.
products:writeCrear y modificar productos.
invoices:readLeer y listar facturas, series y su PDF.
invoices:writeCrear borradores y emitir facturas.

Ciclo de vida de una factura

Emitir una factura son dos pasos separados a propósito: crear el borrador nunca tiene efecto fiscal; emitirlo sí — asigna número de serie, encadena el registro y dispara el envío real a la AEAT (Veri*Factu). Ningún endpoint combina ambas cosas en una sola llamada.

Paso 1

POST /v1/invoices

Crea un borrador (status: "DRAFT") con sus líneas. Sin número, sin efecto fiscal, se puede leer y descartar libremente. Requiere Idempotency-Key — ver más abajo.

Paso 2

POST /v1/invoices/{id}/issue

Emite el borrador contra una serie (seriesId). A partir de aquí la factura es inalterable: número asignado, registro encadenado y envío a la AEAT en marcha.

Idempotencia obligatoria al crear facturas

POST /v1/invoices exige la cabecera Idempotency-Key — un identificador que generas tú (por ejemplo, un UUID por intento de creación desde tu sistema). Repetir la misma petición con la misma clave nunca crea un segundo borrador: devuelve el mismo recurso ya creado.

Sin Idempotency-Key, la petición falla con 400 Bad Request antes de tocar nada — no es opcional. Una factura de verdad no se puede deshacer con un simple DELETE, así que un reintento de red por tu parte nunca debe poder duplicarla.

Reintento con la misma clavecURL
curl -X POST https://api.kullqi.com/v1/invoices \
  -H "Authorization: Bearer sk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: 8f14e45f-ceea-4c9c-8b3d-4a9e5f1c2b90" \
  -H "Content-Type: application/json" \
  -d '{ "contactId": 42, "invoiceType": "F1", "lines": [
    { "description": "Consultoría", "quantity": 1, "unitPrice": 100.00, "taxRate": 21 }
  ] }'

# primera llamada  → 201 Created, id: 17
# repetir EXACTAMENTE la misma Idempotency-Key → 200 OK, mismo id: 17

Límites de uso

Pensados para integraciones reales, no para scraping ni para sustituir el uso normal de la app.

LímiteValor
Cuota diaria por cuenta (tenant)5.000 peticiones / día natural
Ritmo sostenido (gateway)20 peticiones / segundo
Ráfaga máxima (gateway)40 peticiones

Superar la cuota diaria devuelve 429 Too Many Requests con un cuerpo { "message": "..." }; el contador se reinicia a medianoche.

Referencia

Recursos disponibles

Todas las rutas cuelgan de https://api.kullqi.com. Los cuerpos y campos son exactamente los mismos que usa la propia app de Kullqi — nada simplificado ni recortado para la API pública.

Contactos

MétodoRutaScopeDescripción
POST/v1/contactscontacts:writeCrear un contacto (cliente o proveedor).
GET/v1/contactscontacts:readListar contactos, con búsqueda y paginación.
GET/v1/contacts/{id}contacts:readObtener un contacto.
PUT/v1/contacts/{id}contacts:writeActualizar un contacto.
DELETE/v1/contacts/{id}contacts:writeArchivar un contacto (no se elimina el histórico).

Productos

MétodoRutaScopeDescripción
POST/v1/productsproducts:writeCrear un producto o servicio del catálogo.
GET/v1/productsproducts:readListar productos, con búsqueda y paginación.
GET/v1/products/{id}products:readObtener un producto.
PUT/v1/products/{id}products:writeActualizar un producto.

Series de facturación

MétodoRutaScopeDescripción
GET/v1/invoice-seriesinvoices:readListar las series disponibles (necesarias para emitir).

Solo lectura en esta versión de la API: las series se crean y configuran desde la app.

Facturas

MétodoRutaScopeDescripción
POST/v1/invoicesinvoices:writeCrear un borrador. Exige Idempotency-Key.
POST/v1/invoices/{id}/issueinvoices:writeEmitir el borrador — número, cadena de registro y envío a la AEAT.
GET/v1/invoicesinvoices:readListar facturas, con filtros por estado, serie, fechas, contacto.
GET/v1/invoices/{id}invoices:readObtener una factura, con su hash, QR y estado ante la AEAT.
GET/v1/invoices/{id}/pdfinvoices:readDescargar el PDF con el QR de verificación oficial.

Fuera de esta versión de la API: rectificar, anular, registrar cobros y enviar por email — de momento solo desde la app de Kullqi.

Errores

Códigos HTTP estándar. Los errores de validación propios de /v1 devuelven un cuerpo JSON simple: { "message": "..." }.

CódigoSignificado
400Petición inválida — por ejemplo, falta Idempotency-Key en la creación de una factura.
401Clave ausente, mal formada, revocada o expirada.
403La clave es válida pero no tiene el scope necesario para esta ruta.
404El recurso no existe o no pertenece a tu cuenta.
429Cuota diaria o límite de ritmo superado.

Genera tu clave y haz tu primera llamada

Se muestra una sola vez al crearla — cópiala en ese momento.

Ir a Claves de API