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/contacts \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"Cabecera X-API-Key
curl https://api.factuarea.com/v1/contacts \
-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('contacts?limit=10');
$body = json_decode((string) $response->getBody(), true);const res = await fetch('https://api.factuarea.com/v1/contacts?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/contacts',
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. El consentimiento OAuth expone 68 scopes
simples con punto más las macros factuarea.read, factuarea.write y
factuarea.full; estos se traducen a los scopes detallados con dos puntos que
protegen cada endpoint y tool MCP. La política de rotación
aplica también a los secretos de cliente OAuth.
El catálogo de consentimiento incluye price_lists.read/write,
facturae.read/write y tax_reports.read/write. La pantalla ofrece solo los
scopes solicitados por el cliente, nunca preselecciona los sensibles y el token
emitido contiene exactamente el subconjunto aprobado por el usuario.
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.
El catálogo válido es de solo adición para credenciales existentes, mientras que
el subconjunto asignable a una clave nueva sigue la superficie API publicada.
Los cuatro scopes reservados de GoCardless/MONEI que aparecen debajo siguen
reconociéndose por compatibilidad histórica, pero se omiten de
CreateApiKeyV1Request y no pueden asignarse hasta que se publiquen esos
proveedores. Después se aplican por separado las restricciones de plan y
sandbox mediante scope_not_allowed_by_plan y
scope_not_allowed_in_sandbox.
Clientes y catálogo
| Scope | Permite |
|---|---|
contacts:read | Listar y consultar contactos. |
contacts:write | Crear y actualizar contactos, roles y perfiles. |
contacts:delete | Archivar contactos y retirar roles sin referencias. |
products:read | Listar y consultar productos. |
products:write | Crear y actualizar productos. |
products:delete | Eliminar productos. |
price_lists:read | Listar tarifas, sus ítems y resolver precios de catálogo. |
price_lists:write | Crear, actualizar y eliminar tarifas y sus ítems. |
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. |
Integraciones y observabilidad
| Scope | Permite |
|---|---|
stripe_autoinvoicing:read | Leer el estado, configuración y cuentas conectadas de la autofacturación Stripe. |
stripe_autoinvoicing:write | Configurar la autofacturación Stripe y sus cuentas conectadas. |
payouts:read | Leer payouts de Stripe y su estado de conciliación. |
integration_events:read | Inspeccionar eventos de pasarela recibidos y sus motivos tipados de descarte. |
integration_events:write | Reprocesar eventos de integración aparcados. |
developers:read | Inspeccionar el log de peticiones API de la empresa autenticada. |
emails:read | Inspeccionar el estado y el historial de emails enviados. |
gocardless_autoinvoicing:read | Reservado para la integración GoCardless aún no publicada; ningún endpoint ni tool lo requiere hoy. |
gocardless_autoinvoicing:write | Reservado para la integración GoCardless aún no publicada; ningún endpoint ni tool lo requiere hoy. |
monei_autoinvoicing:read | Reservado para la integración MONEI aún no publicada; ningún endpoint ni tool lo requiere hoy. |
monei_autoinvoicing:write | Reservado para la integración MONEI aún no publicada; ningún endpoint ni tool lo requiere hoy. |
Control horario
Estos scopes requieren el módulo de plan control_horario. Algunos scopes de
lectura se pueden conceder por OAuth; las escrituras y transiciones privilegiadas
siguen siendo exclusivas de API key.
| Scope | Permite |
|---|---|
employees:read | Leer empleados y el estado de sus invitaciones. |
employees:write | Crear, actualizar y gestionar empleados y plazas. |
employees:delete | Eliminar empleados permanentemente. |
time_entries:read | Leer fichajes, balances y registros mensuales. |
time_entries:write | Fichar, corregir y cerrar/reabrir registros horarios. |
absences:read | Leer tipos, políticas, solicitudes y saldos de ausencia. |
absences:write | Crear y actualizar configuración y solicitudes de ausencia. |
absences:transition | Aprobar, rechazar y cancelar solicitudes de ausencia. |
work_schedules:read | Leer horarios y asignaciones. |
work_schedules:write | Crear, actualizar, asignar y archivar horarios. |
presence:read | Leer la presencia en vivo y diaria. |
holidays:read | Leer festivos de empresa y regionales. |
payroll_exports:read | Leer exportaciones de nómina generadas. |
payroll_exports:write | Generar exportaciones de nómina. |
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 pueden gestionar desde el dashboard de desarrolladores (app.factuarea.com/settings/developers/api-keys) o mediante los endpoints v1 self-service. Ambas superficies permiten crear, rotar y revocar claves; el dashboard también configura la 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, está revocada/caducada o el secreto no coincide con el hash almacenado. |
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.
Credenciales para integraciones
Las operaciones REST y MCP de tiendas requieren una API key con los scopes de tiendas. El consentimiento OAuth no concede estos scopes. Autoriza por separado la conexión del proveedor: una clave de Factuarea no es una credencial de WooCommerce o Shopify. La autenticación MCP también requiere un cliente compatible con la revisión 2026-07-28.