Autenticación y seguridad
La API pública se autentica solo con API key. Esta página explica cómo enviarla, qué puede hacer cada clave y qué límites tiene.
Enviar la clave
Añade la cabecera X-API-Key a cada petición:
curl -s https://app.faxtal.com/api/v1.1/company \
-H "X-API-Key: $FAXTAL_API_KEY"
- Es la única forma de autenticarse: la API pública no admite
Authorization: Bearerni sesiones de usuario. - Llama siempre por HTTPS.
GET /api/v1.1/healthes la única operación que no pide clave.
Formato de la clave
Una clave tiene esta forma (valor ficticio):
fctXXXXXXXX_YYYYYYYYYYYYYYYY
- Tiene tres partes: el prefijo
fct, un identificador y, tras un guion bajo, el secreto. - Envíala entera y sin espacios. El secreto también puede contener
_y-. - Faxtal no guarda el secreto en claro. Por eso no puede volver a mostrarte una clave.
Ciclo de vida
Las claves se gestionan en la aplicación, en Configuración → API Keys, con el rol Propietario o Admin. Los pasos están en Crear y gestionar API keys.
| Acción | Qué pasa |
|---|---|
| Crear | La clave se muestra una sola vez. Puedes darle una fecha de caducidad. |
| Rotar | Se crea una clave nueva. Decides si la anterior se revoca en ese momento o sigue funcionando hasta que la revoques. |
| Revocar | La clave deja de funcionar al momento. |
| Caducar | Al llegar su fecha de caducidad, la clave deja de funcionar. |
Una clave revocada, caducada o mal copiada recibe la misma respuesta, 401:
{
"detail": {
"code": "unauthorized",
"message": "Invalid credentials",
"request_id": "4f1c0a9e2b7d4e5f8a6b3c2d1e0f9a8b"
}
}
Si falta la cabecera, message es Missing credentials.
Empresa de la clave
- Cada clave pertenece a una empresa y la API trabaja siempre sobre ella. La empresa no va en la URL.
- Los recursos de otra empresa no existen para tu clave: la API responde
404. GET /api/v1.1/companyte dice a qué empresa pertenece la clave.
Permisos (scopes)
Cada operación exige un permiso. Si la credencial no lo tiene, la API responde 403:
{
"detail": {
"code": "scope_missing",
"message": "La credencial no tiene permiso para esta operación.",
"scope": "invoices:issue",
"request_id": "4f1c0a9e2b7d4e5f8a6b3c2d1e0f9a8b"
}
}
Una clave sin permisos definidos tiene acceso completo.
:::info Los permisos y la lista de IP permitidas aún no se pueden configurar desde la aplicación. Las claves que creas allí tienen acceso completo desde cualquier IP. :::
| Permiso | Qué permite | Por ejemplo |
|---|---|---|
invoices:read | Consultar facturas, documentos, terceros y productos, y validar sin guardar | GET /issued-invoices, GET /drafts/{invoice_id}, GET /issued-invoices/{invoice_id}/pdf, POST /issued-invoices/validate, GET /third-parties |
invoices:write | Guardar y borrar borradores, enviar facturas por email y gestionar documentos de emitidas | PUT /drafts, POST /drafts/batch, DELETE /drafts/{invoice_id}, POST /issued-invoices/{invoice_id}/send, POST /issued-invoices/{invoice_id}/documents |
invoices:issue | Emitir, importar, anular y borrar emitidas | POST /issued-invoices/{invoice_id}/issue, POST /issued-invoices/import, POST /issued-invoices/{invoice_id}/cancel, DELETE /issued-invoices/{invoice_id} |
received:write | Reconocer, registrar y borrar recibidas y sus documentos | PUT /received-invoices, POST /received-invoices/import, POST /received-invoices/recognize, DELETE /received-invoices/{invoice_id} |
parties:write | Crear y actualizar terceros | PUT /third-parties |
payments:read | Consultar los cobros de emitidas y los pagos de recibidas | GET /issued-invoices/{invoice_id}/payments, GET /received-invoices/{invoice_id}/payments |
payments:write | Registrar, corregir y compensar cobros y pagos | POST /issued-invoices/{invoice_id}/payments, POST /received-invoices/{invoice_id}/payments/{payment_id}/reverse, POST /issued-invoices/{invoice_id}/payments/compensate |
compliance:read | Consultar certificados y el estado de VeriFactu y del SII | GET /certificates, GET /verifactu/submissions, GET /verifactu/incidents, GET /sii/pending |
*concede todos los permisos.invoices:*concede todos los deinvoices, y lo mismo con los demás prefijos.GET /companyyGET /companiesno exigen permiso.- Cambiar la configuración de VeriFactu o del SII (
PUT /verifactu/config,PUT /sii/config) y registrar eventos SIF (POST /verifactu/sif) exigen acceso completo.
Restricción por IP
- Una clave puede llevar una lista de direcciones IP o rangos CIDR, IPv4 o IPv6, desde los que se admite.
- Desde cualquier otra IP, la API responde
403conip_forbidden.
Límites de uso
Peticiones por minuto
- Cada clave admite hasta 120 peticiones por minuto. El contador vuelve a cero al empezar cada minuto de reloj.
- Al superarlo, la API responde
429conrate_limitedy estas cabeceras:
| Cabecera | Valor |
|---|---|
Retry-After | Segundos que faltan para poder volver a llamar |
X-RateLimit-Limit | Peticiones admitidas por minuto |
X-RateLimit-Remaining | 0 |
X-RateLimit-Reset | Momento en que vuelve a cero el contador, en segundos Unix |
- Las respuestas correctas no llevan estas cabeceras.
- Espera lo que indica
Retry-Afterantes de reintentar. Para volúmenes grandes, usa los lotes:POST /drafts/batchyPOST /issued-invoices/import/batch.
Plan
- Si el plan de la empresa no incluye la API, cualquier llamada autenticada responde
402confeature_outside_plany"feature": "api_access". - Algunas funciones dependen además del plan, como el catálogo de productos. Si el plan no las incluye,
402confeature_outside_plany la funcionalidad enfeature. - Si la empresa ha agotado el cupo anual de facturas de su plan, crear una factura nueva, también un borrador, responde
402conquota_exceeded,limityused. Emitidas y recibidas tienen cupos separados. Actualizar una factura que ya existe no consume cupo.
Buenas prácticas
- Guarda la clave en tu servidor, en un gestor de secretos o en una variable de entorno. Nunca en el código fuente, en un repositorio ni en una aplicación que se ejecute en el navegador o en el móvil.
- Usa una clave por integración. Así puedes revocar una sin parar las demás.
- Ponle fecha de caducidad y rótala antes de que llegue.
- Para rotar sin cortes: rota sin revocar la anterior, despliega la clave nueva y revoca la antigua.
- Si sospechas que se ha filtrado, revócala en ese momento.
- No escribas la clave en tus logs. Guarda el
request_idde las respuestas de error.