Documentación de la API
Cómo conectar tu sistema: clientes, consumo, documentos, presupuestos y albaranes.
URL base de la API: https://ticket.quantumpyme.com/api/v1 · versión 1.5.0
Cada petición lleva tu clave en Authorization: Bearer …. Puedes crearla en Claves de API. Importa la especificación OpenAPI en Postman, Insomnia o tu generador de clientes.
API v1 — Guía para partners
API REST para gestionar desde tu sistema a tus clientes de Quantum Contable, consultar su consumo, y subir, sincronizar y revisar sus documentos. La especificación completa y siempre al día está en `openapi.yaml` (OpenAPI 3.1: impórtala en Postman, Insomnia o genera un cliente con tu lenguaje). Esta guía explica cómo se usa.
Base: https://ticket.quantumpyme.com/api/v1
1. Primeros pasos
- Contrato. Para escribir o leer datos de tus clientes hace falta el contrato de encargo del tratamiento (art. 28 RGPD) firmado con QuantumPYME. Lo firma el administrador de tu equipo desde el apartado «Contrato» de tu panel, en unos minutos. Sin él, esos permisos no se pueden crear y devuelven
403 contract_required. - Clave. En tu panel de socio → «Claves de API», crea una clave con los permisos que necesites. Se muestra una sola vez: guárdala como un secreto (gestor de secretos o variable de entorno; nunca en el código ni en los logs).
- Prueba.
curl https://ticket.quantumpyme.com/api/v1/me -H "Authorization: Bearer qt_live_xxxxxxxx_…"
Devuelve tu partner, los permisos de la clave y el límite de peticiones.
2. Permisos de la clave
| Permiso | Para qué | Contrato |
|---|---|---|
clients:read | Listar y ver clientes | No |
clients:write | Crear y modificar clientes, desactivarlos y vincular su WhatsApp | Sí |
usage:read | Consumo y saldo | No |
documents:read | Leer documentos | Sí |
documents:write | Subir PDF o imágenes para leerlos con IA, enviar documentos con los datos ya extraídos, y corregir, confirmar o descartar documentos | Sí |
webhooks:manage | Avisos automáticos | Sí |
commercial:read | Leer presupuestos y albaranes | Sí |
commercial:write | Crear y modificar presupuestos y albaranes | Sí |
messages:write | Reenviar a nuestro asistente lo que escribe o manda un cliente (chatbot) | Sí |
Da a cada clave solo lo que necesita. Puedes limitarla por IP y ponerle caducidad desde el panel. Por defecto caduca al año: cuando falte poco, crea otra y revoca la anterior.
qt_live_… y actúan sobre datos reales (los clientes que crees cuentan, y sus documentos gastan saldo). Para probar, crea clientes con un externalId reconocible (por ejemplo PRUEBA-…) y desactívalos al terminar.3. Convenciones
- Paginación:
limit(1–100, por defecto 50) ycursor. Cada lista devuelve{ "data": [...], "nextCursor": "…" | null }; sigue pidiendo concursor=<nextCursor>hasta que seanull. - Errores:
{ "error": { "code", "message", "requestId", "details"? } }con el código HTTP correspondiente. Programa contracode, no contramessage. Guarda elrequestId(también va en la cabeceraX-Request-Id) si contactas con soporte. - Límite: 60 peticiones por minuto y clave. Al pasarte recibes
429 rate_limited: espera y reintenta. La subida de documentos tiene sus propios límites (ver el apartado 6). - Aislamiento: solo ves y modificas clientes de tu partner. Un cliente o documento de otro partner responde
404, igual que uno inexistente. - Fechas: ISO 8601 en UTC; las fechas de documento,
AAAA-MM-DD.
Códigos de error frecuentes en clientes:
| Código | HTTP | Significado |
|---|---|---|
invalid_parameter | 400 | Un campo falta o no es válido (el mensaje dice cuál). El cuerpo es estricto: un campo desconocido es un error |
plan_required / invalid_plan | 400 | Con comisión el plan es obligatorio y debe ser de su tipo (cliente o gestoría) |
plans_not_applicable | 409 | Con bolsas no hay planes |
external_id_in_use | 409 | Ya tienes un cliente con ese externalId; error.details.clientId es el existente |
email_in_use | 409 | El email ya está registrado en Quantum Contable. Si se repite muchas veces seguidas (más de 20 al día), 429 rate_limited |
whatsapp_already_linked | 409 | El cliente ya tiene un WhatsApp vinculado |
client_inactive | 409 | El cliente está desactivado |
partner_suspended | 409 | Tu cuenta de partner está suspendida |
client_not_found | 404 | No existe o no es tuyo |
4. Flujo: dar de alta un cliente que trabajará por WhatsApp
El cliente no entra al panel: tú lo das de alta desde tu sistema y él manda sus tickets por WhatsApp.
1. Crear el cliente (clients:write):
curl -X POST https://ticket.quantumpyme.com/api/v1/clients \
-H "Authorization: Bearer $QT_KEY" -H "Content-Type: application/json" \
-d '{ "nombre": "Taller Rodríguez SL", "email": "info@tallerrodriguez.es", "plan": "starter", "externalId": "ERP-1042", "limiteDocsMes": 80 }'- Con comisión,
planes obligatorio (starter,professional,business; para una gestoríatipo: "gestoria"ygestorias_s|m|l). Con bolsas no lleva plan. externalIdes tu identificador. Hace segura la reintentación: si la petición se corta y la repites, no se crea un duplicado; recibes409 external_id_in_usecon elclientIdque ya existe.limiteDocsMeses el tope mensual de ese cliente (0= sin límite; si no lo pones, rige el límite por defecto de tu cuenta).- No se envía ninguna invitación al cliente.
2. Vincular su WhatsApp. El número no se fija desde tu sistema: lo vincula el propio cliente enviando un código desde su móvil, para que nadie quede vinculado a un número que no es suyo. Pide el código:
curl -X POST https://ticket.quantumpyme.com/api/v1/clients/CLIENT_ID/whatsapp-link -H "Authorization: Bearer $QT_KEY"
# → { "code": "K7M2QX", "expiresAt": "2026-10-20T16:30:00.000Z", "whatsappNumber": "+34876084424" }Dile al cliente que envíe ese código desde su móvil por WhatsApp al número whatsappNumber. Caduca en 30 minutos; si pides otro, el anterior deja de valer. Cuando el cliente lo envía, su número queda vinculado y ya puede mandar fotos o PDF de sus tickets y facturas. Comprueba whatsappVinculado en GET /clients/{id}.
whatsappNumber es tu número propio si lo tienes activo y, si no, el de Quantum Contable.
3. Gestionarlo después: PATCH /clients/{id} (nombre, sector, externalId, plan, límite; telefono: null desvincula el WhatsApp), POST /clients/{id}/deactivate y /reactivate. El email y el tipo no se cambian por la API.
5. Consumo y saldo (usage:read)
GET /usage: tu modelo (bagocommission), clientes activos y totales, documentos del periodo y, con bolsas, el saldo (bag.balance), el estado (ok,gracia,agotada,sin_bolsa) y la próxima caducidad.GET /usage/clientsyGET /clients/{id}/usage: documentos del periodo y límite efectivo de cada cliente (limitSource:client,partner_defaultonone).
Consumo por mes (para facturar a tus clientes). Añade ?month=2026-11 (mes natural, hora de Madrid) a cualquiera de los tres endpoints y cada respuesta incluye month: { month, documents, byChannel } con los documentos de ese mes y de qué canal vinieron (whatsapp, api, email, factura). Con /usage/clients?month=… recorres a todos tus clientes (con nextCursor) y obtienes la tabla para cobrar. El histórico empieza el día en que se activó esta función; los meses anteriores no están.
Mensajes de WhatsApp (solo con bolsas). Cada mes están incluidos 1.000 mensajes de WhatsApp salientes (las respuestas que enviamos a tus clientes por WhatsApp). Desde el 1.001, cada mensaje de más cuesta 0,021 € sin IVA y se descuenta de tu bolsa, en documentos equivalentes, al cierre del mes (importe ÷ precio por documento de tu bolsa, redondeado hacia arriba). Los mensajes que iniciamos nosotros fuera de las 24 h de una conversación no entran en los incluidos y se cobran desde el primero. Los mensajes por API (/messages) y por correo no cuentan. Con ?month= en GET /usage recibes whatsapp: { sent, included, billable, pricePerMessageEur, amountEur, documentsDeducted, closed }; también lo ves en el panel, en Bolsas. Te avisamos por correo al llegar a 800 y al superar los 1.000.
Con bolsas, el estado gracia significa que te has quedado sin saldo pero los documentos siguen entrando durante el margen pactado: te conviene comprar otra bolsa antes de agotada, cuando sus clientes dejan de poder enviar. Se avisa al 20 % del saldo.
6. Documentos y webhooks
- Documentos: lista, filtros y sincronización incremental con
actualizadoDesde; subida de archivos y revisión (corregir, confirmar, descartar). - Webhooks: avisos firmados (HMAC-SHA256) cuando un documento se crea o cambia.
Flujo: subir un documento desde tu aplicación y revisarlo
Para que tu cliente trabaje solo en tu aplicación, sin entrar al panel de Quantum Contable. Permiso documents:write (y documents:read para consultar).
- Subes el archivo:
POST /clients/{clientId}/documents, enmultipart/form-datacon el archivo en el campofile(PDF, JPG, PNG o WebP, hasta 10 MB). Respondemos al momento (202) con eldocumentIdy el estadoprocesando. - Lo leemos con IA (unos segundos). Te llega el webhook
document.needs_review(odocument.processed), o lo consultas conGET /documents/{documentId}. - Tu usuario revisa los datos en tu aplicación.
- Cierras el documento:
PATCH /documents/{id}si hay que corregir algo, y despuésPOST /documents/{id}/confirmpara darlo por bueno oPOST /documents/{id}/excludepara descartarlo.
curl -X POST https://ticket.quantumpyme.com/api/v1/clients/CLIENT_ID/documents \
-H "Authorization: Bearer $QT_KEY" -H "Idempotency-Key: factura-0042" \
-F "file=@factura.pdf"
# → 202 { "documentId": "clx…", "estado": "procesando", "paginas": 1, "documentsConsumed": 1, "duplicateOf": null }Cuánto cuenta. Un PDF de hasta 3 páginas cuenta como 1 documento de tu bolsa o del límite del cliente; con más páginas, 1 por cada bloque de 3 (máximo 30 páginas). documentsConsumed lo indica. Un archivo repetido o uno que no se puede leer no descuenta nada.
Si tu chatbot reenvía lo que escribe tu cliente. POST /clients/{id}/messages (permiso messages:write): con {"text": "…"} nuestro asistente lo interpreta (consultas de cifras, búsqueda de documentos, presupuestos y facturas si el cliente tiene el módulo) y devuelve sus respuestas en replies para que las muestres; nada sale por WhatsApp. Si awaitingReply es true, el asistente ha preguntado algo y el siguiente mensaje de ese cliente es la contestación. Con un archivo (multipart, campo file, text opcional como pie de foto) sigue el flujo de documentos de arriba (202 y webhook).
curl -X POST https://ticket.quantumpyme.com/api/v1/clients/CLIENT_ID/messages \
-H "Authorization: Bearer $QT_KEY" -H "Content-Type: application/json" -d '{"text":"¿Cuánto llevo gastado este mes?"}'
# → 200 { "replies": [{ "type": "text", "text": "…" }], "awaitingReply": false }Si ya lees tú los documentos. Envía los datos extraídos en JSON a POST /clients/{id}/documents/data (mismos nombres de campo que GET /documents/{id}: emisor, fecha, numero, lineasIVA, retencionIRPF…). Contesta 201, el documento queda en pendiente_revision y cuenta 1 documento. Un total que no cuadra es 400 total_mismatch; un documento ya registrado es 409 duplicate_document (repite con allowDuplicate: true si es otro distinto).
curl -X POST https://ticket.quantumpyme.com/api/v1/clients/CLIENT_ID/documents/data \
-H "Authorization: Bearer $QT_KEY" -H "Idempotency-Key: factura-0042" -H "Content-Type: application/json" \
-d '{"emisor":{"nombre":"Ferretería Pepe","nif":"B12345678"},"fecha":"2026-11-03","numero":"F-0042","lineasIVA":[{"tipo":21,"base":100,"cuota":21}]}'Por correo del cliente. Cada cliente puede conectar desde su portal («Buzón de correo») una cuenta dedicada a documentos: leemos sus correos nuevos en solo lectura y los PDF o imágenes adjuntos se registran como documentos pendientes de revisión, con la misma regla de cuenta y descuento de tu bolsa. Los ves en GET /documents y en el desglose por canal de /usage?month= (email).
Reintentos. Con la cabecera Idempotency-Key, repetir la petición no duplica nada. Si ese mismo archivo ya estaba registrado para el cliente, recibes 200 con duplicateOf y documentsConsumed: 0.
Límites por clave. 30 subidas por minuto y 10 documentos esperando a procesarse, además de un máximo diario por partner. Si los superas, 429 (rate_limited, too_many_pending o daily_limit) con error.details.retryAfter en segundos. Si vas a cargar un histórico grande, avísanos del volumen.
Estados. procesando → pendiente_revision → confirmado o excluido; error si no se pudo leer (no descuenta nada y puedes volver a enviarlo).
| Código | HTTP | Significado |
|---|---|---|
file_required / invalid_content_type | 400 | Falta el archivo o no es multipart/form-data |
unsupported_file_type / invalid_pdf | 400 | Formato no admitido (se comprueba el contenido, no la extensión) o PDF dañado o con contraseña |
too_many_pages | 400 | El PDF tiene más de 30 páginas |
file_too_large | 413 | El archivo supera los 10 MB |
quota_exhausted | 409 | El cliente o tu bolsa no tienen documentos disponibles |
idempotency_key_reused | 409 | Esa Idempotency-Key ya se usó con otro archivo u otro cliente |
document_locked | 409 | Ingreso de una factura emitida desde Quantum Contable: se rectifica, no se edita |
multiple_vat_lines / vat_breakdown_missing | 409 | No se puede cambiar la base ni el tipo de IVA en ese documento (ver Documentos) |
document_not_found | 404 | No existe o es de otro partner |
Lo que todavía no hace: no hay un webhook para un error de lectura (consúltalo con GET), no se cambia un documento de gasto a ingreso ni al revés, y un documento excluido no se reabre.
Patrón recomendado: webhook para enterarte al momento (document.processed, document.needs_review, document.updated) y una sincronización incremental nocturna con GET /documents?actualizadoDesde=… como red de seguridad.
7. Presupuestos y albaranes
Tus clientes pueden emitir presupuestos y albaranes (desde su panel, por WhatsApp o por tu sistema) y tú los sincronizas por API. Son documentos no fiscales: no entran en la contabilidad ni en VERI*FACTU; solo la factura final cuenta.
409 module_not_enabled; pide a QuantumPYME que se los active.Ciclo de vida
| Estados | |
|---|---|
| Presupuesto | emitido → aceptado · rechazado · anulado · convertido (en albarán) · facturado |
| Albarán | emitido → entregado · anulado · facturado |
Cada documento recibe su número al crearse (P-2026-0001, A-2026-0001): correlativo por cliente, tipo y año, sin huecos; uno anulado conserva su número. «Caducado» no es un estado: es un presupuesto emitido con caducado: true (su validoHasta ya pasó). Solo se modifica mientras está emitido.
Crear (desde tu sistema)
curl -X POST https://ticket.quantumpyme.com/api/v1/clients/CLIENT_ID/quotes \
-H "Authorization: Bearer $QT_KEY" -H "Content-Type: application/json" \
-d '{ "cliente": { "nombre": "Construcciones Pérez SA", "nif": "A58818501" },
"lineas": [{ "concepto": "Reparación del cuadro", "cantidad": 1, "precioUnitario": "450", "tipoIva": 21 }],
"externalId": "PRE-1042", "numeroExterno": "PRE-1042" }'Igual para /clients/{id}/delivery-notes (con "valorado": false para un albarán sin precios en el PDF).
Cómo no pisaros los números. Quantum Contable numera los suyos (numeroFormato) y tu sistema los suyos: guarda el tuyo en numeroExterno (único por tipo) y el identificador interno en externalId. Cada documento llega con los dos.
Sincronización en los dos sentidos
- Tu sistema → Quantum: crea con
POSTy unexternalId. Es seguro reintentar: si ya existe recibes409 external_id_in_useconerror.details.documentId. - Quantum → tu sistema: los documentos que el cliente crea desde su panel o por WhatsApp (
origen: "manual"o"whatsapp") los recoges conGET /quotesyGET /delivery-notesyactualizadoDesde=<la mayor actualizadoEn que viste>. Cada cambio de estado (aceptado, entregado…) hace que el documento reaparezca. Los avisos por webhook de estos documentos llegarán más adelante: mientras tanto, consulta cada pocos minutos. - Cambiar de estado:
POST /quotes/{id}/accept|reject|cancel|convert,POST /delivery-notes/{id}/deliver|cancel.convertcrea un albarán con las líneas del presupuesto (origenIdapunta a él). - Facturación: si facturas en tu sistema, marca el documento con
POST …/invoicedy la referencia de tu factura (facturaReferencia). Si el cliente factura desde su panel, el documento pasa afacturado. - PDF:
GET /quotes/{id}/pdfyGET /delivery-notes/{id}/pdf.
Importes como texto decimal ("121.00") para no perder céntimos. Un partner solo ve los documentos de sus clientes creados desde que son suyos.
8. Buenas prácticas
- Reintenta con espera creciente ante
429y5xx; nunca ante4xx(salvo429). - Guarda el
idde Quantum junto a tuexternalId. - Rota la clave ante cualquier sospecha y revoca las que ya no uses (panel → Claves de API). Si pierdes una clave, avísanos de inmediato.
- Trata los datos recibidos conforme a tu contrato de encargo: solo para prestar el servicio a cada cliente, con acceso restringido y cifrado en tus sistemas.
Cambios
- 1.5 (noviembre 2026): consumo por mes y canal (
?month=AAAA-MMen/usage,/usage/clientsy/clients/{id}/usage, con el bloquewhatsappde los mensajes incluidos y de más); documentos con los datos ya extraídos (POST /clients/{id}/documents/data,201,Idempotency-Key,409 duplicate_document,400 total_mismatch); mensajes de tu chatbot a nuestro asistente (POST /clients/{id}/messages, permisomessages:write). Los clientes pueden además conectar su correo desde su portal y sus adjuntos entran como documentos (canalemail). Sin cambios que rompan lo anterior. - 1.4 (octubre 2026): el WhatsApp de un cliente ya no se fija con
telefonoal crearlo o modificarlo: se vincula con el código dewhatsapp-linkque el cliente envía desde su móvil (telefono: nullenPATCHsigue desvinculando). Muchosemail_in_useseguidos dan429 rate_limited. Las claves nuevas caducan al año por defecto. - 1.3 (octubre 2026): subida de documentos (
POST /clients/{id}/documents, asíncrona, conIdempotency-Key) y revisión (PATCH /documents/{id},POST /documents/{id}/confirmy/exclude), con el permisodocuments:write.GET /documents/{id}devuelveestado: procesandooerrormientras una subida no ha terminado. - 1.2 (octubre 2026): presupuestos y albaranes (
/quotes,/delivery-notes, con alta bajo/clients/{id}/…), conexternalIdynumeroExternopara sincronizar con tu sistema, y permisoscommercial:readycommercial:write. - 1.1 (octubre 2026): escritura de clientes (
POST/PATCH /clients,deactivate,reactivate), vinculación de WhatsApp (whatsapp-link), consumo (/usage,/usage/clients,/clients/{id}/usage) y permisosclients:writeyusage:read.GET /clientsdevuelve ademástipo,plan,limiteDocsMes,docsMesywhatsappVinculado. Especificación OpenAPI. - 1.0: lectura de clientes y documentos, y webhooks.
Próximamente: webhooks de presupuestos y albaranes, un aviso por webhook cuando falla la lectura de una subida, y exportaciones (A3, Holded).