Errores y validaciones
Las respuestas de error de la API pública siguen siempre la misma forma base, independientemente del recurso. Esta guía documenta los códigos HTTP que verás, el formato JSON, y cómo distinguir entre los distintos tipos.
Forma general de la respuesta
Toda respuesta de error tiene como mínimo:
{
"statusCode": 400,
"message": "Mensaje legible que explica el problema"
}
Puede incluir además:
type— categoría del error cuando aplica.errors— array con detalles por campo en errores de validación (solo en400 ValidationError).
Content-Type siempre es application/json.
Códigos HTTP
Código | Significado típico |
| El cuerpo o los parámetros no cumplen el contrato. Si es un fallo de validación de campos, viene con |
| Falta credencial, está expirada o es inválida. Ver Autenticación. |
| Credencial válida pero sin los scopes necesarios, o sin acceso a la empresa indicada en el path. |
| El recurso no existe o no pertenece a la empresa del path. |
| La operación choca con el estado actual: identificador duplicado, borrado de un recurso con dependencias, etc. |
| Demasiadas escrituras simultáneas del mismo tipo en la empresa. Reintenta con backoff. Ver Límite de peticiones. |
| Error inesperado del servidor. No es un error del cliente; conviene reintentar tras un retraso. |
Errores de validación (400)
Cuando el body o los parámetros fallan el JSON Schema, la respuesta incluye un array errors con un objeto por cada problema:
{
"statusCode": 400,
"message": "Validation failed",
"type": "ValidationError",
"errors": [
{
"path": "content.main.fiscalId",
"message": "Formato de NIF/CIF inválido para España"
},
{
"path": "content.main.lines.0.unitPrice",
"message": "Debe ser un número mayor que 0"
}
]
}
Cada entrada del array localiza el campo problemático y explica qué falla. Para integraciones que muestran el error al usuario final, basta con mostrar el message de cada entrada; el path ayuda al developer a depurar.
Errores de negocio (400, 409)
Algunos errores no son fallos de schema sino reglas de negocio:
Crear una factura con una serie ya consumida.
Borrar un contacto que tiene documentos asociados.
Modificar un presupuesto convertido en factura.
Estos errores vienen como 400 o 409 (según el caso) con un message descriptivo. Cuando el mensaje incluye datos relevantes (ID de documento bloqueante, valor duplicado), se devuelven en campos adicionales del JSON.
Errores de autenticación y autorización (401, 403)
401— el token o la API key son rechazados antes de evaluar permisos. Casos típicos: token expirado, API key revocada, header mal formado.403— la credencial es válida pero le falta algo:Scopes insuficientes para la operación (por ejemplo, intentar
POSTcon scoperead).La empresa del path no es accesible para esta credencial.
Para detalles del flujo de auth y rotación de tokens, ver Autenticación.
Límites del plan
Cuando una operación no puede completarse porque la empresa supera una capacidad del plan contratado, la respuesta incluye el código estable plan_limit_exceeded dentro de errors:
{
"statusCode": 403,
"message": "La empresa está en modo solo lectura por exceder el límite de clientes contratados (10). Por favor, amplia tu suscripción o reduce el número de clientes de tu empresa.",
"errors": [
{
"message": "La empresa está en modo solo lectura por exceder el límite de clientes contratados (10). Por favor, amplia tu suscripción o reduce el número de clientes de tu empresa.",
"code": "plan_limit_exceeded"
}
]
}
El mismo código se devuelve al crear una factura con el cupo del plan agotado (por año natural: 100 en Gratis, 2.000 en Bronce, 5.000 en Plata y 12.000 en Oro; sin cupo en Diamante). Solo bloquea crear facturas: el resto de operaciones sigue disponible y la ampliación es subir de plan.
Se comportan igual otras capacidades: número de empleados, productos, productos con control de stock, campos personalizados, almacenes y documentos recurrentes activos. En todos los casos, el mensaje indica el tope alcanzado.
El estado HTTP es siempre 403. Usa errors[].code, no el texto por separado, para identificar este caso. No reintentes la misma operación hasta ampliar el plan o reducir el uso que supera la capacidad.
Funcionalidades no incluidas en el plan
El mismo código plan_limit_exceeded identifica el 403 de una funcionalidad entera que el plan no incluye: las escrituras de pedidos y órdenes de compra («Los pedidos de cliente y las órdenes de compra no están disponibles en tu plan») y las operaciones de stock de productos («El control de stock no está disponible en tu plan»). La diferencia con un tope de capacidad está solo en el mensaje: aquí no hay uso que reducir, y la salida es un plan o un módulo que incluya la funcionalidad.
FacturaDirecta también envía un e-mail de aviso al propietario de la empresa, al usuario que hizo la solicitud —o al creador de la API key— y a los usuarios con permiso completo de configuración de empresa. El aviso identifica la petición y el motivo. Se envía como máximo una vez por empresa cada 7 días, aunque el error se repita.
Recursos no encontrados (404)
404 significa siempre una de estas dos cosas:
El ID no existe en la empresa indicada.
El ID existe pero pertenece a otra empresa (la API no revela que el recurso existe en otro tenant).
Trata ambos casos como "no existe para mí" en tu integración.
Estrategia recomendada de manejo
Diferencia errores del cliente (4xx) de errores del servidor (5xx). Los 4xx no deben reintentarse sin cambiar el input; los 5xx sí, con backoff exponencial.
Para
400 ValidationError, recorreerrors[]y muestra al usuario losmessageespecíficos en vez delmessagegeneral.Idempotencia. Repetir un
POST /contactscon el mismofiscalIdda409 Conflict, no duplicado. Aprovecha esto para reintentos seguros en sincronizaciones.No deduzcas estado a partir del código HTTP solo. Combina código y contenido (
type,message,errors[].code) para clasificar el error en tu lógica.
Ejemplo completo
Petición que viola dos validaciones (CIF mal formado y línea con precio negativo):
HTTP/1.1 400 Bad Request
Content-Type: application/json{
"statusCode": 400,
"message": "Validation failed",
"type": "ValidationError",
"errors": [
{
"path": "content.main.fiscalId",
"message": "Formato de NIF/CIF inválido para España"
},
{
"path": "content.main.lines.0.unitPrice",
"message": "Debe ser un número mayor que 0"
}
]
}
Y conflicto al borrar un contacto con factura asociada:
HTTP/1.1 409 Conflict
Content-Type: application/json{
"statusCode": 409,
"message": "No se puede borrar el contacto: tiene 3 facturas asociadas"
}