Autenticación
API keys con prefijos fact_live_ / fact_test_, scopes granulares, los scopes privilegiados accounts:*, qué alcanza el consentimiento OAuth, 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 que emite un titular o administrador de la cuenta en el
dashboard de desarrolladores
(app.factuarea.com/settings/developers/api-keys),
o mediante los endpoints v1 self-service. Una clave pertenece
a una cuenta, nunca a un solo NIF. Su alcance es su ámbito: los NIF
asignados a ella, que pueden ser NIF de la cuenta y NIF de otra cuenta que te
deja alcanzarlos. Cada ruta de NIF nombra en su propio path aquel sobre el que
opera (/v1/companies/{company}/…), y cada ruta de cuenta nombra tu cuenta
(/v1/accounts/{account}/…). GET /v1/me enumera el ámbito —una entrada por
NIF, con el id opaco que espera el path y su tax_id—, así que una
credencial nunca tiene que adivinar a qué NIF llega. 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 tus NIF reales (producción);fact_test_alcanza solo la empresa sandbox aislada de tu cuenta, 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 o en la respuesta de la API. Si la pierdes, debes rotarla.
- Almacenamiento: el backend solo almacena un hash con clave (HMAC-SHA256) del secreto, nunca el secreto. No hay forma de recuperarlo.
Todos los ejemplos de esta guía usan una clave fact_live_. Una clave
fact_test_ funciona en las mismas rutas, pero solo sobre la empresa sandbox
de tu cuenta: toma su id de GET /v1/me y úsalo como {company}. 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/companies/{company}/contacts \
-H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"Cabecera X-API-Key
curl https://api.factuarea.com/v1/companies/{company}/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('companies/{company}/contacts?limit=10');
$body = json_decode((string) $response->getBody(), true);const res = await fetch('https://api.factuarea.com/v1/companies/{company}/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/companies/{company}/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 catálogo de consentimiento OAuth tiene
73 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. Un scope
del catálogo, payroll_exports.write, no se ofrece, porque ninguna tool exige
el scope al que se traduce.
Qué alcanza el consentimiento OAuth
El consentimiento concede los datos de negocio de un NIF y nunca la administración de la cuenta. Un scope detallado queda fuera de alcance cuando el catálogo no tiene ningún scope con punto que se traduzca a él, y estos están excluidos a propósito, para que la app de un tercero no pueda obtenerlos aunque el usuario apruebe lo que sea:
| Tipo | Scopes que el consentimiento nunca concede | Por qué |
|---|---|---|
| Administración de la cuenta | account:write, account:owner, members:read, members:write, invitations:read, invitations:write, nif_transfers:read, nif_transfers:write, companies:read, companies:write, companies:delete, api_keys:read, api_keys:write | Las claves, el equipo, la titularidad, los traspasos de NIF y la cartera de NIF son decisiones del titular de la cuenta en su propia sesión. |
| Privilegio de proveedor | accounts:read, accounts:write | Aprovisionar, administrar y cobrar las cuentas de tus clientes nunca se delega por consentimiento. |
| Observabilidad | developers:read, emails:read, integration_events:read, integration_events:write | Exponen la actividad técnica de las credenciales, el historial de correo y los eventos de las pasarelas de pago de la cuenta, y reprocesar uno de esos eventos puede emitir una factura real. |
| Pagos y tiendas | stripe_autoinvoicing:read, stripe_autoinvoicing:write, payouts:read, stores:read, stores:write, woocommerce_store:write, shopify_store:write | Se ofrecen al canal de integración de la cuenta mediante una API key. |
| Escrituras irreversibles, fiscales y laborales | verifactu:write, delivery_notes:gdpr_forget, automations:delete, absences:write, absences:transition, time_entries:write, work_schedules:write | Cambian registros fiscales, borran datos o actúan en nombre de responsables laborales, así que quedan en manos de controles first-party o del titular mediante una API key. |
Todo lo demás que traduce el catálogo es alcanzable: contactos, catálogo,
documentos de venta, compras y facturas recurrentes, informes fiscales, FacturaE,
lecturas de VeriFactu, webhooks, automatizaciones y lecturas de jornada, y
account:read mediante profile.read. Algunas operaciones quedan fuera de OAuth
aunque su scope sea alcanzable, como los webhooks y los registros de peticiones de
la cuenta: Tools de MCP muestra el canal de cada tool. Usa una API
key para cada scope excluido, también con el servidor MCP.
Scopes de MCP lista el catálogo de consentimiento.
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 falla la validación con
422 invalid_param_value 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: un scope se concede solo si el plan de todos
los NIF del ámbito de la clave lo permite.
Contactos y catálogo
Cliente y proveedor son dos roles de la misma identidad —el contacto—, así
que un solo trío de scopes cubre los dos. Los antiguos clients:* y
suppliers:* están retirados y ya no se pueden asignar.
| Scope | Permite |
|---|---|
contacts:read | Listar y consultar contactos, en cualquiera de sus roles. |
contacts:write | Crear y actualizar contactos, roles y perfiles. |
contacts:delete | Archivar o eliminar contactos y retirar sus roles. |
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 gastos. |
purchase_invoices:write | Crear y actualizar gastos. |
purchase_invoices:delete | Eliminar gastos. |
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 de impuestos de Factuarea y los impuestos propios de tu empresa. |
taxes:write | Crear y actualizar los impuestos propios de tu empresa y fijar sus predeterminados. |
taxes:delete | Eliminar los impuestos propios de tu empresa. |
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. |
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 y consultar webhook endpoints y sus entregas, de un NIF y de la cuenta. |
webhooks:write | Crear, actualizar, rotar, probar y hacer ping a webhook endpoints, y relanzar o reintentar sus entregas. |
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 un NIF y de la cuenta. |
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. |
Tareas y proyectos
projects:* y tasks:* requieren el módulo tasks, que incluyen todos los
planes; users:read y notifications:* son transversales. Los scopes projects:delete y tasks:delete
son solo de API key: un consentimiento OAuth nunca los concede. Facturar las
horas de un proyecto necesita además invoices:write. Consulta
Proyectos y tareas.
| Scope | Permite |
|---|---|
projects:read | Listar y consultar proyectos, columnas y definiciones de campos personalizados; leer el resumen de tiempo; exportar tareas; previsualizar facturas de horas. |
projects:write | Crear y actualizar proyectos, columnas y definiciones de campos personalizados; archivar y desarchivar; importar tareas. |
projects:delete | Borrar de forma permanente proyectos, columnas y definiciones de campos personalizados. |
tasks:read | Buscar y consultar tareas, comentarios, relaciones, vínculos, adjuntos, imputaciones de tiempo, actividad y etiquetas; leer la agenda y el temporizador en marcha. |
tasks:write | Crear y actualizar tareas, comentarios, relaciones, etiquetas, vínculos, adjuntos e imputaciones de tiempo; cambiar el estado y la persona asignada; arrancar y detener el temporizador. |
tasks:delete | Borrar de forma permanente tareas, comentarios, adjuntos, imputaciones de tiempo y etiquetas. |
users:read | Listar los miembros de la empresa y consultar el usuario actual. |
notifications:read | Listar las notificaciones de quien tiene la key. |
notifications:write | Marcar notificaciones como leídas. |
Cartera de NIF
Scopes detallados para los NIF que tiene tu cuenta. Funcionan sobre
/v1/accounts/{account}/companies… y necesitan una API key: el consentimiento
nunca los concede. Cualquier cuenta, en cualquier plan, lista y consulta sus
propios NIF, así que companies:* no tiene gate de plan. Lo que el plan
controla es añadir un NIF que paga la cuenta, y lo hace dentro de la operación
(NIF adicionales).
| Scope | Permite |
|---|---|
companies:read | Listar y consultar los NIF de la cuenta, sus estadísticas, su estado de creación y su aptitud para emitir, la vista previa del cargo de un NIF adicional y el resumen consolidado de cumplimiento de jornada. |
companies:write | Dar de alta, editar, activar y desactivar NIF de la cuenta, y verificar la creación de uno. |
companies:delete | Archivar un NIF de la cuenta. |
Cartera de NIF describe las operaciones.
Administración de la cuenta
Scopes para lo que tiene la propia cuenta: sus claves, su equipo y su titularidad.
Necesitan una API key, salvo account:read, que el consentimiento OAuth concede
mediante profile.read. No son privilegiados, así que el super-scope * sí los
cubre.
| Scope | Permite | Plan |
|---|---|---|
account:read | Listar y consultar las API keys de la cuenta, y leer su consumo, su facturación, las plantillas de su personalización y la verificación censal AEAT de un NIF. | Cualquier plan |
account:write | Crear, cambiar los NIF de, rotar y revocar las API keys de la cuenta, y actualizar la personalización. | Cualquier plan |
account:owner | Transferir la titularidad de la cuenta. La persona que hay detrás de la clave debe ser el titular actual. | Cualquier plan |
members:read | Leer los miembros de la cuenta, sus grants y sus restricciones de módulo. | Requiere el módulo user_management |
members:write | Añadir, cambiar y eliminar miembros, fijar y revocar sus grants y cambiar sus restricciones de módulo. | Requiere el módulo user_management |
invitations:read | Listar y consultar las invitaciones de la cuenta. | Requiere el módulo user_management |
invitations:write | Enviar, reenviar y revocar invitaciones. | Requiere el módulo user_management |
nif_transfers:read | Listar los traspasos de NIF que emitió la cuenta. | Requiere el módulo user_management |
nif_transfers:write | Emitir, aceptar y revocar un traspaso de NIF. | Requiere el módulo user_management |
api_keys:read, api_keys:write, api_keys:delete | Reservados: ningún endpoint ni tool los exige. | Cualquier plan |
GET /v1/me no necesita ningún scope: cualquier credencial válida puede
introspeccionarse. En un plan sin el módulo user_management los scopes
members:*, invitations:* y nif_transfers:* no se pueden asignar a una
clave, y GET /v1/me lista solo los efectivos. Los planes empresario y
enterprise incluyen el módulo.
Las API keys no se gestionan con api_keys:*. Los seis endpoints de
/v1/accounts/{account}/api-keys los gobiernan account:read (listar y
consultar) y account:write (crear, cambiar los NIF de, rotar el secret y
revocar) — consulta API keys y
claves acotadas. Cuentas y NIF
describe el equipo y los traspasos.
Scopes privilegiados
Dos scopes son privilegiados: accounts:read y accounts:write. Permiten que
una cuenta aprovisione, administre y cobre cuentas para sus clientes, lo que
describe cuentas gestionadas. Se distinguen de todos
los demás scopes:
| Scope | Permite |
|---|---|
accounts:read | Listar y consultar las cuentas gestionadas de tu cuenta, leer su consumo de aprovisionamiento y la vista previa de un cambio de plan, y descargar la plantilla de una importación masiva. |
accounts:write | Aprovisionar una cuenta gestionada, cambiar su plan y su nivel, reemitir su vale, terminar su gestión, y previsualizar y aplicar una importación masiva. |
- Factuarea los concede, cuenta por cuenta. Solo Factuarea puede: la API no
tiene ninguna operación que conceda el privilegio.
GET /v1/mete dice si tu cuenta lo tiene, enaccount.is_provideryaccount.privileged_scopes. No puedes asignártelos: crear una clave que los lista sin el privilegio responde403 privileged_scope_requiredy no crea nada. - Se comprueban en cada petición. La clave debe listar el scope, tu cuenta
debe tener hoy el privilegio y la persona que emitió la clave debe seguir siendo
titular o administrador de tu cuenta. Si falla cualquiera de las tres, la
respuesta es
403 privileged_scope_required, y las dos causas responden igual. Nada sale de una caché: si retiramos el privilegio, o esa persona deja de ser titular o administrador, la misma clave deja de funcionar en su siguiente petición. - No llegan por OAuth. El consentimiento nunca los concede: usa una API key, también con el servidor MCP.
- Ningún plan los controla. El gate es el privilegio, no el plan.
*no los cubre. Consulta el super-scope.
Super-scope
| Scope | Permite |
|---|---|
* | Acceso total — equivalente a tener todos los demás scopes anteriores, salvo los privilegiados accounts:read y accounts:write. Reservado para migraciones puntuales. Evita usarlo en integraciones de producción. |
* no cubre accounts:*. Una clave que solo lleva * responde
403 insufficient_scope en una operación
privilegiada, por amplia que parezca. * sí cubre el resto de la cuenta: las
claves, el equipo, la titularidad y los traspasos de NIF. Una clave con *
necesita operate en cada NIF al que llega, y con el privilegio puedes listar
* y accounts:* juntos.
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": "Esta operación requiere el scope 'account:write'. Tu API key solo tiene los scopes: ninguno.",
"doc_url": "https://docs.factuarea.com/guides/errors#insufficient_scope",
"request_id": "req_01JBVH7K9Y4N3CDQ2EHJB1AGSV"
}
}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 y fijar la lista de acceso por IP al crear una; el dashboard también la edita después. El dashboard es para los titulares y administradores de la cuenta, y las claves que emites nunca llegan a más que tú: quién puede emitir una key lo explica.
Los metadatos de la clave autenticada (id, name, prefix, scopes, tier,
environment, last_used_at, expires_at) se pueden leer vía GET /v1/me,
junto con los NIF a los que llega la clave — 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. La rotación deja el secreto anterior válido durante la ventana de gracia de 24 horas, así que, para cortar de golpe un secreto expuesto, revoca la clave en su lugar (la revocación es inmediata) y emite una nueva.
- 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 cuenta y alcanzan solo los NIF de su ámbito; 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 o con ip_allowlist al crear la clave. Si el request llega desde una
IP fuera de la lista de acceso, la respuesta es 401 con el código
ip_not_allowed 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 cuando
la clave autentica pero no basta) 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 | El secreto es correcto, pero la clave se revocó. |
api_key_expired | 401 | El secreto es correcto, pero la clave superó su expires_at. |
ip_not_allowed | 401 | El request llega desde una IP fuera de la lista de acceso de la clave. |
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. * no cubre los privilegiados accounts:*. |
privileged_scope_required | 403 | La operación exige un scope privilegiado y la cuenta no tiene el privilegio, o la persona que emitió la clave ya no es titular ni administrador. |
live_credential_required | 403 | Una clave fact_test_ intenta cambiar la cuenta: sus claves, su equipo, su titularidad, sus traspasos o su cartera de NIF. |
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, y a una clave que solo lleva scopes:readle basta conviewen sus NIF. - Da a cada clave solo los NIF que necesita, con
scoped_company_ids(claves acotadas). - 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.