Autenticación
API keys con prefijos fact_live_ / fact_test_, scopes granulares, rotación con periodo de gracia y lista de acceso por IP.
La API de Factuarea autentica cada request con una API key. Las claves
son tokens opacos generados en el dashboard de desarrolladores
(app.factuarea.com/settings/developers/api-keys)
y vinculados a una empresa concreta. Cada request a
https://api.factuarea.com/v1/* debe incluir una clave válida en uno de los
dos formatos soportados.
Formato de la API key
fact_live_<24 alphanumeric characters>
fact_test_<24 alphanumeric characters>Ejemplo:
fact_live_8KqW3pXnR2VbY7TcA9eFmN5z
fact_test_3pXnR2VbY7TcA9eFmN5z8KqW- Prefijo: determina el entorno.
fact_live_opera sobre tu empresa real (producción);fact_test_opera sobre una empresa sandbox aislada con los efectos externos (VeriFactu → AEAT, FACe, emails, webhooks) desactivados. El prefijo te permite identificar el entorno sin decodificar la clave. Consulta Modo de prueba y sandbox. - Secreto: 24 caracteres base62 → ~143 bits de entropía. Se muestra solo una vez al crearla en el dashboard. Si la pierdes, debes rotarla.
- Hash en BD: el backend solo almacena el hash bcrypt cost-12 del secreto. No hay forma de recuperarlo.
Todos los ejemplos de esta guía usan una clave fact_live_, pero el mismo
request funciona con una clave fact_test_ — basta con cambiar el prefijo para operar
sobre datos de sandbox. Crea y valida tu integración primero en test. Consulta
Modo de prueba y sandbox.
Enviar la clave en cada request
La API acepta dos formatos equivalentes. Elige el que mejor encaje con tu cliente:
Authorization Bearer (recomendado)
curl https://api.factuarea.com/v1/clients \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"Cabecera X-API-Key
curl https://api.factuarea.com/v1/clients \
-H "X-API-Key: fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"Envía solo una de las dos cabeceras. Si ambas están presentes, la
cabecera Authorization: Bearer tiene prioridad.
Ejemplos por lenguaje
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.factuarea.com/v1/',
'headers' => [
'Authorization' => 'Bearer ' . getenv('FACTUAREA_API_KEY'),
'Accept' => 'application/json',
],
]);
$response = $client->get('clients?limit=10');
$body = json_decode((string) $response->getBody(), true);const res = await fetch('https://api.factuarea.com/v1/clients?limit=10', {
headers: {
Authorization: `Bearer ${process.env.FACTUAREA_API_KEY}`,
Accept: 'application/json',
},
});
const data = await res.json();import os
import requests
resp = requests.get(
'https://api.factuarea.com/v1/clients',
params={'limit': 10},
headers={
'Authorization': f"Bearer {os.environ['FACTUAREA_API_KEY']}",
'Accept': 'application/json',
},
)
resp.raise_for_status()
data = resp.json()OAuth 2.1
Para integraciones de agente y apps de terceros que actúan en nombre de
un usuario de Factuarea, la API también admite el flujo OAuth 2.1
authorization-code con PKCE (code_challenge_method=S256) como
alternativa a una API key estática. Los mismos scopes protegen
el access token, y la política de rotación aplica
también a los secretos de cliente OAuth.
Los metadatos de discovery (RFC 8414) se publican en
/.well-known/oauth-authorization-server, para que los clientes OAuth
resuelvan los endpoints de autorización y token automáticamente:
curl https://api.factuarea.com/.well-known/oauth-authorization-serverEl esquema de seguridad OAuth2 — incluidas las URL de autorización y
token y la lista completa de scopes — se describe en la
Referencia de la API.
Scopes
Cada API key se crea con uno o más scopes que limitan qué
endpoints puede invocar. Los scopes son cadenas con la forma
<resource>:<action>. El catálogo es cerrado: cualquier scope fuera del
conjunto listado provoca invalid_scope al crear la clave.
Clientes y catálogo
| Scope | Permite |
|---|---|
clients:read | Listar y consultar clientes. |
clients:write | Crear y actualizar clientes. |
clients:delete | Eliminar clientes. |
products:read | Listar y consultar productos. |
products:write | Crear y actualizar productos. |
products:delete | Eliminar productos. |
suppliers:read | Listar y consultar proveedores. |
suppliers:write | Crear y actualizar proveedores. |
suppliers:delete | Eliminar proveedores. |
Documentos de venta
| Scope | Permite |
|---|---|
invoices:read | Listar y consultar facturas. |
invoices:write | Crear y actualizar facturas (incluye duplicar y rectificativa). |
invoices:delete | Eliminar borradores de factura. |
invoices:send | Enviar factura por email al cliente. |
invoices:void | Anular una factura emitida. |
quotes:read | Listar y consultar presupuestos. |
quotes:write | Crear y actualizar presupuestos. |
quotes:delete | Eliminar presupuestos. |
quotes:send | Enviar presupuesto por email. |
quotes:transition | Aceptar, rechazar o convertir presupuestos. |
proformas:read | Listar y consultar facturas proforma. |
proformas:write | Crear y actualizar facturas proforma. |
proformas:delete | Eliminar facturas proforma. |
proformas:send | Enviar factura proforma por email. |
proformas:transition | Convertir factura proforma en factura. |
delivery_notes:read | Listar y consultar albaranes. |
delivery_notes:write | Crear y actualizar albaranes. |
delivery_notes:delete | Eliminar albaranes. |
delivery_notes:transition | Marcar como entregado/cancelado, firmar, convertir. |
delivery_notes:gdpr_forget | Borrar la PII de auditoría de firma (RGPD Art. 17). |
Compras y recurrentes
| Scope | Permite |
|---|---|
purchase_invoices:read | Listar y consultar facturas de compra. |
purchase_invoices:write | Crear y actualizar facturas de compra. |
purchase_invoices:delete | Eliminar facturas de compra. |
purchase_invoices:transition | Marcar como pagada, recibida, contabilizada. |
recurring_invoices:read | Listar y consultar plantillas recurrentes. |
recurring_invoices:write | Crear y actualizar plantillas recurrentes. |
recurring_invoices:delete | Eliminar plantillas recurrentes. |
recurring_invoices:transition | Pausar, reanudar y emitir manualmente. |
Catálogos y exportación
| Scope | Permite |
|---|---|
taxes:read | Leer el catálogo (global) de tipos impositivos. |
taxes:write | Crear y actualizar tipos impositivos. |
taxes:delete | Eliminar tipos impositivos. |
series:read | Listar series de numeración de facturas. |
series:write | Crear y actualizar series de numeración de facturas. |
pdfs:read | Descargar PDFs de cualquier documento con el scope :read correspondiente. |
tax_reports:read | Leer informes fiscales (Modelo 303/347, etc.). |
tax_reports:write | Generar informes fiscales. |
account:read | Leer la cuenta autenticada (GET /v1/account). |
account:write | Gestionar las API keys de la propia cuenta (crear, rotar, revocar) y actualizar la personalización de la cuenta. |
VeriFactu y FacturaE
| Scope | Permite |
|---|---|
verifactu:read | Leer registros, eventos, certificados y configuración de VeriFactu. |
verifactu:write | Gestionar certificados, ajustes y reintentos de VeriFactu. |
facturae:read | Descargar el XML FacturaE de una factura y leer sus envíos a FACe. |
facturae:write | Enviar facturas a FACe y solicitar la anulación de envíos. |
Webhooks y eventos
| Scope | Permite |
|---|---|
webhooks:read | Listar webhook endpoints y entregas. |
webhooks:write | Crear, actualizar, rotar y hacer ping a webhook endpoints. |
webhooks:delete | Eliminar webhook endpoints. |
events:read | Leer el catálogo de eventos y eventos individuales. |
Empresas gestionadas (gestoría)
Scopes detallados para el modelo de gestoría, donde una cuenta maestra
gestiona empresas hijas y sus API keys. Solo accesibles con API key (sin
equivalente en el consentimiento OAuth); companies:* requiere además el módulo
del plan de gestoría.
| Scope | Permite |
|---|---|
companies:read | Listar y consultar las empresas gestionadas (sub-cuentas hijas). |
companies:write | Crear, actualizar, activar y desactivar empresas gestionadas. |
companies:delete | Archivar empresas gestionadas. |
api_keys:read | Listar y consultar las API keys de las empresas gestionadas. |
api_keys:write | Crear, rotar y revocar las API keys de las empresas gestionadas. |
api_keys:delete | Eliminar permanentemente las API keys de las empresas gestionadas. |
Super-scope
| Scope | Permite |
|---|---|
* | Acceso total — equivalente a tener todos los demás scopes anteriores. Reservado para claves de owner / migraciones puntuales. Evita usarlo en integraciones de producción. |
Si un request usa un endpoint que requiere un scope no concedido a la
clave, la respuesta es 403 con type: authorization_error y
code: insufficient_scope.
{
"error": {
"type": "authorization_error",
"code": "insufficient_scope",
"message": "La API key no tiene el scope requerido para esta operación.",
"request_id": "req_01JBVH7..."
}
}Gestión de claves
Las API keys se gestionan desde el dashboard de desarrolladores
(app.factuarea.com/settings/developers/api-keys),
no a través de la API pública. Desde ahí puedes crear claves, rotar su
secreto, revocarlas, configurar scopes, un expires_at opcional y una
lista de acceso por IP.
Los metadatos de la clave autenticada (id, name, prefix, scopes, tier,
last_used_at, expires_at) se pueden leer vía GET /v1/account — pero el
secreto nunca se devuelve.
No hay ningún endpoint para "ver" el secreto. Solo se muestra una vez al crearlo. Si pierdes el valor debes rotar la clave en el dashboard y volver a desplegar el nuevo secreto. Es deliberado: minimiza la ventana de exposición.
Política de rotación
Las API keys y los secretos de cliente OAuth son credenciales de larga vida y deben rotarse en un calendario y de inmediato tras cualquier sospecha de filtración.
- Los prefijos son la fuente de verdad del entorno:
fact_live_(producción) yfact_test_(sandbox). Nunca los mezcles entre entornos. - Rota desde el dashboard (o mediante los
endpoints self-service
account:write) para emitir un secreto nuevo. El nuevo secreto se devuelve una sola vez — guárdalo de inmediato, no se vuelve a mostrar. - Ventana de gracia (doble secreto). Tras una rotación el secreto
anterior sigue funcionando durante una ventana de gracia de 24
horas, para que puedas desplegar el nuevo secreto sin tiempo de
inactividad. Durante esa ventana se aceptan tanto el nuevo como el
anterior; al expirar la ventana el secreto anterior se rechaza y se
purga. Un request que siga usando el secreto anterior recibe un header
199Warningque indica cuántas horas quedan antes de que deje de funcionar. - Cuándo rotar: en un calendario regular (p. ej. cada 90 días), siempre que un miembro del equipo con acceso se vaya, e inmediatamente si un secreto queda expuesto alguna vez en logs, control de versiones o un cliente público.
- Revoca para invalidar una clave permanentemente. Cualquier request
posterior con ella falla con
401. La revocación no tiene ventana de gracia — es instantánea e irreversible.
Los secretos están ligados a una sola empresa (tenant) y nunca deben incrustarse en navegadores, apps móviles ni ningún cliente público — mantenlos solo en el servidor.
Lista de acceso por IP
Cada API key se puede restringir a una lista de IPs o rangos CIDR desde el
dashboard. Si el request llega desde una IP fuera de la lista de acceso, la
respuesta es 401 y el incidente se registra en el log de auditoría. Deja
la lista de acceso vacía para permitir cualquier IP.
Errores de autenticación
Los fallos relacionados con la API key responden con HTTP 401 (o 403 para
insufficient_scope) y el envoltorio de error estándar. El campo code
distingue el caso:
code | HTTP | Causa |
|---|---|---|
missing_api_key | 401 | No se ha enviado ninguna cabecera de autenticación. |
invalid_api_key | 401 | La clave no existe, tiene un formato incorrecto o el secreto no coincide con el hash almacenado. |
api_key_revoked | 401 | La clave fue revocada o ha expirado. Crea una nueva en el dashboard. |
too_many_auth_failures | 429 | Demasiados intentos de autenticación fallidos; espera antes de reintentar. |
insufficient_scope | 403 | La clave carece del scope que requiere el endpoint. |
Cada respuesta incluye un request_id único (también en la
cabecera X-Request-Id) que puedes facilitar a soporte al investigar.
{
"error": {
"type": "authentication_error",
"code": "invalid_api_key",
"message": "La API key proporcionada no es válida.",
"request_id": "req_01JBVH7K9Y4N3CDQ2EHJB1AGSV",
"doc_url": "https://docs.factuarea.com/guides/errors#invalid_api_key"
}
}Buenas prácticas
- Nunca subas API keys a repositorios — usa variables de entorno o un gestor de secretos (AWS Secrets Manager, Doppler, 1Password Service Accounts).
- Crea una clave por integración: facilita rotar y auditar el acceso sin afectar al resto.
- Limita los scopes al mínimo necesario. Un script de exportación solo necesita
scopes
:readconcretos. - Activa la lista de acceso por IP para integraciones servidor a servidor con IPs estables.
- Configura
expires_atpara claves temporales (p. ej. consultorías, demos). - Audita el uso desde el dashboard:
Developers > API Keys > Activitymuestra IPs, rutas y errores por clave.