Factuarea API

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-server

El 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.

ScopePermite
clients:readListar y consultar clientes.
clients:writeCrear y actualizar clientes.
clients:deleteEliminar clientes.
products:readListar y consultar productos.
products:writeCrear y actualizar productos.
products:deleteEliminar productos.
suppliers:readListar y consultar proveedores.
suppliers:writeCrear y actualizar proveedores.
suppliers:deleteEliminar proveedores.

Documentos de venta

ScopePermite
invoices:readListar y consultar facturas.
invoices:writeCrear y actualizar facturas (incluye duplicar y rectificativa).
invoices:deleteEliminar borradores de factura.
invoices:sendEnviar factura por email al cliente.
invoices:voidAnular una factura emitida.
quotes:readListar y consultar presupuestos.
quotes:writeCrear y actualizar presupuestos.
quotes:deleteEliminar presupuestos.
quotes:sendEnviar presupuesto por email.
quotes:transitionAceptar, rechazar o convertir presupuestos.
proformas:readListar y consultar facturas proforma.
proformas:writeCrear y actualizar facturas proforma.
proformas:deleteEliminar facturas proforma.
proformas:sendEnviar factura proforma por email.
proformas:transitionConvertir factura proforma en factura.
delivery_notes:readListar y consultar albaranes.
delivery_notes:writeCrear y actualizar albaranes.
delivery_notes:deleteEliminar albaranes.
delivery_notes:transitionMarcar como entregado/cancelado, firmar, convertir.
delivery_notes:gdpr_forgetBorrar la PII de auditoría de firma (RGPD Art. 17).

Compras y recurrentes

ScopePermite
purchase_invoices:readListar y consultar facturas de compra.
purchase_invoices:writeCrear y actualizar facturas de compra.
purchase_invoices:deleteEliminar facturas de compra.
purchase_invoices:transitionMarcar como pagada, recibida, contabilizada.
recurring_invoices:readListar y consultar plantillas recurrentes.
recurring_invoices:writeCrear y actualizar plantillas recurrentes.
recurring_invoices:deleteEliminar plantillas recurrentes.
recurring_invoices:transitionPausar, reanudar y emitir manualmente.

Catálogos y exportación

ScopePermite
taxes:readLeer el catálogo (global) de tipos impositivos.
taxes:writeCrear y actualizar tipos impositivos.
taxes:deleteEliminar tipos impositivos.
series:readListar series de numeración de facturas.
series:writeCrear y actualizar series de numeración de facturas.
pdfs:readDescargar PDFs de cualquier documento con el scope :read correspondiente.
tax_reports:readLeer informes fiscales (Modelo 303/347, etc.).
tax_reports:writeGenerar informes fiscales.
account:readLeer la cuenta autenticada (GET /v1/account).
account:writeGestionar las API keys de la propia cuenta (crear, rotar, revocar) y actualizar la personalización de la cuenta.

VeriFactu y FacturaE

ScopePermite
verifactu:readLeer registros, eventos, certificados y configuración de VeriFactu.
verifactu:writeGestionar certificados, ajustes y reintentos de VeriFactu.
facturae:readDescargar el XML FacturaE de una factura y leer sus envíos a FACe.
facturae:writeEnviar facturas a FACe y solicitar la anulación de envíos.

Webhooks y eventos

ScopePermite
webhooks:readListar webhook endpoints y entregas.
webhooks:writeCrear, actualizar, rotar y hacer ping a webhook endpoints.
webhooks:deleteEliminar webhook endpoints.
events:readLeer 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.

ScopePermite
companies:readListar y consultar las empresas gestionadas (sub-cuentas hijas).
companies:writeCrear, actualizar, activar y desactivar empresas gestionadas.
companies:deleteArchivar empresas gestionadas.
api_keys:readListar y consultar las API keys de las empresas gestionadas.
api_keys:writeCrear, rotar y revocar las API keys de las empresas gestionadas.
api_keys:deleteEliminar permanentemente las API keys de las empresas gestionadas.

Super-scope

ScopePermite
*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) y fact_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 199 Warning que 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:

codeHTTPCausa
missing_api_key401No se ha enviado ninguna cabecera de autenticación.
invalid_api_key401La clave no existe, tiene un formato incorrecto o el secreto no coincide con el hash almacenado.
api_key_revoked401La clave fue revocada o ha expirado. Crea una nueva en el dashboard.
too_many_auth_failures429Demasiados intentos de autenticación fallidos; espera antes de reintentar.
insufficient_scope403La 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 :read concretos.
  • Activa la lista de acceso por IP para integraciones servidor a servidor con IPs estables.
  • Configura expires_at para claves temporales (p. ej. consultorías, demos).
  • Audita el uso desde el dashboard: Developers > API Keys > Activity muestra IPs, rutas y errores por clave.

En esta página