Factuarea API

Autenticació

API keys amb prefixos fact_live_ / fact_test_, scopes granulars, rotació amb període de gràcia i llista d'accés per IP.

L'API de Factuarea autentica cada request amb una API key. Les claus són tokens opacs generats al dashboard de desenvolupadors (app.factuarea.com/settings/developers/api-keys) i vinculats a una empresa concreta. Cada request a https://api.factuarea.com/v1/* ha d'incloure una clau vàlida en un dels dos formats admesos.

Format de l'API key

fact_live_<24 alphanumeric characters>
fact_test_<24 alphanumeric characters>

Exemple:

fact_live_8KqW3pXnR2VbY7TcA9eFmN5z
fact_test_3pXnR2VbY7TcA9eFmN5z8KqW
  • Prefix: determina l'entorn. fact_live_ opera sobre la teva empresa real (producció); fact_test_ opera sobre una empresa sandbox aïllada amb els efectes externs (VeriFactu → AEAT, FACe, emails, webhooks) desactivats. El prefix et permet identificar l'entorn sense descodificar la clau. Consulta Mode de prova i sandbox.
  • Secret: 24 caràcters base62 → ~143 bits d'entropia. Es mostra només una vegada en crear-la al dashboard. Si la perds, l'has de rotar.
  • Hash a la BD: el backend només emmagatzema el hash bcrypt cost-12 del secret. No hi ha cap manera de recuperar-lo.

Tots els exemples d'aquesta guia usen una clau fact_live_, però el mateix request funciona amb una clau fact_test_ — només cal canviar el prefix per operar sobre dades de sandbox. Crea i valida la teva integració primer en test. Consulta Mode de prova i sandbox.

Enviar la clau a cada request

L'API accepta dos formats equivalents. Tria el que millor encaixi amb el teu client:

Authorization Bearer (recomanat)

curl https://api.factuarea.com/v1/clients \
  -H "Authorization: Bearer fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"

Capçalera X-API-Key

curl https://api.factuarea.com/v1/clients \
  -H "X-API-Key: fact_live_8KqW3pXnR2VbY7TcA9eFmN5z"

Envia només una de les dues capçaleres. Si totes dues hi són presents, la capçalera Authorization: Bearer té prioritat.

Exemples per llenguatge

$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

Per a integracions d'agent i apps de tercers que actuen en nom d'un usuari de Factuarea, l'API també admet el flux OAuth 2.1 authorization-code amb PKCE (code_challenge_method=S256) com a alternativa a una API key estàtica. Els mateixos scopes protegeixen l'access token, i la política de rotació aplica també als secrets de client OAuth.

Les metadades de discovery (RFC 8414) es publiquen a /.well-known/oauth-authorization-server, perquè els clients OAuth resolguin els endpoints d'autorització i token automàticament:

curl https://api.factuarea.com/.well-known/oauth-authorization-server

L'esquema de seguretat OAuth2 — incloses les URL d'autorització i token i la llista completa de scopes — es descriu a la Referència de l'API.

Scopes

Cada API key es crea amb un o més scopes que limiten quins endpoints pot invocar. Els scopes són cadenes amb la forma <resource>:<action>. El catàleg és tancat: qualsevol scope fora del conjunt llistat provoca invalid_scope en crear la clau.

Clients i catàleg

ScopePermet
clients:readLlistar i consultar clients.
clients:writeCrear i actualitzar clients.
clients:deleteEliminar clients.
products:readLlistar i consultar productes.
products:writeCrear i actualitzar productes.
products:deleteEliminar productes.
suppliers:readLlistar i consultar proveïdors.
suppliers:writeCrear i actualitzar proveïdors.
suppliers:deleteEliminar proveïdors.

Documents de venda

ScopePermet
invoices:readLlistar i consultar factures.
invoices:writeCrear i actualitzar factures (inclou duplicar i rectificativa).
invoices:deleteEliminar esborranys de factura.
invoices:sendEnviar factura per email al client.
invoices:voidAnul·lar una factura emesa.
quotes:readLlistar i consultar pressupostos.
quotes:writeCrear i actualitzar pressupostos.
quotes:deleteEliminar pressupostos.
quotes:sendEnviar pressupost per email.
quotes:transitionAcceptar, rebutjar o convertir pressupostos.
proformas:readLlistar i consultar factures proforma.
proformas:writeCrear i actualitzar factures proforma.
proformas:deleteEliminar factures proforma.
proformas:sendEnviar factura proforma per email.
proformas:transitionConvertir factura proforma en factura.
delivery_notes:readLlistar i consultar albarans.
delivery_notes:writeCrear i actualitzar albarans.
delivery_notes:deleteEliminar albarans.
delivery_notes:transitionMarcar com a lliurat/cancel·lat, signar, convertir.
delivery_notes:gdpr_forgetEsborrar la PII d'auditoria de signatura (RGPD Art. 17).

Compres i recurrents

ScopePermet
purchase_invoices:readLlistar i consultar factures de compra.
purchase_invoices:writeCrear i actualitzar factures de compra.
purchase_invoices:deleteEliminar factures de compra.
purchase_invoices:transitionMarcar com a pagada, rebuda, comptabilitzada.
recurring_invoices:readLlistar i consultar plantilles recurrents.
recurring_invoices:writeCrear i actualitzar plantilles recurrents.
recurring_invoices:deleteEliminar plantilles recurrents.
recurring_invoices:transitionPausar, reprendre i emetre manualment.

Catàlegs i exportació

ScopePermet
taxes:readLlegir el catàleg (global) de tipus impositius.
taxes:writeCrear i actualitzar tipus impositius.
taxes:deleteEliminar tipus impositius.
series:readLlistar sèries de numeració de factures.
series:writeCrear i actualitzar sèries de numeració de factures.
pdfs:readDescarregar PDFs de qualsevol document amb el scope :read corresponent.
tax_reports:readLlegir informes fiscals (Modelo 303/347, etc.).
tax_reports:writeGenerar informes fiscals.
account:readLlegir el compte autenticat (GET /v1/account).
account:writeGestionar les API keys del propi compte (crear, rotar, revocar) i actualitzar la personalització del compte.

VeriFactu i FacturaE

ScopePermet
verifactu:readLlegir registres, esdeveniments, certificats i configuració de VeriFactu.
verifactu:writeGestionar certificats, ajustos i reintents de VeriFactu.
facturae:readDescarregar l'XML FacturaE d'una factura i llegir els seus enviaments a FACe.
facturae:writeEnviar factures a FACe i sol·licitar l'anul·lació d'enviaments.

Webhooks i esdeveniments

ScopePermet
webhooks:readLlistar webhook endpoints i lliuraments.
webhooks:writeCrear, actualitzar, rotar i fer ping a webhook endpoints.
webhooks:deleteEliminar webhook endpoints.
events:readLlegir el catàleg d'esdeveniments i esdeveniments individuals.

Empreses gestionades (gestoria)

Scopes detallats per al model de gestoria, on un compte mestre gestiona empreses filles i les seves API keys. Només accessibles amb API key (sense equivalent al consentiment OAuth); companies:* requereix a més el mòdul del pla de gestoria.

ScopePermet
companies:readLlistar i consultar les empreses gestionades (subcomptes fills).
companies:writeCrear, actualitzar, activar i desactivar empreses gestionades.
companies:deleteArxivar empreses gestionades.
api_keys:readLlistar i consultar les API keys de les empreses gestionades.
api_keys:writeCrear, rotar i revocar les API keys de les empreses gestionades.
api_keys:deleteEliminar permanentment les API keys de les empreses gestionades.

Super-scope

ScopePermet
*Accés total — equivalent a tenir tots els altres scopes anteriors. Reservat per a claus d'owner / migracions puntuals. Evita usar-lo en integracions de producció.

Si un request usa un endpoint que requereix un scope no concedit a la clau, la resposta és 403 amb type: authorization_error i 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ó de claus

Les API keys es gestionen des del dashboard de desenvolupadors (app.factuarea.com/settings/developers/api-keys), no a través de l'API pública. Des d'allà pots crear claus, rotar el seu secret, revocar-les, configurar scopes, un expires_at opcional i una llista d'accés per IP.

Les metadades de la clau autenticada (id, name, prefix, scopes, tier, last_used_at, expires_at) es poden llegir via GET /v1/account — però el secret mai es retorna.

No hi ha cap endpoint per "veure" el secret. Només es mostra una vegada en crear-lo. Si perds el valor has de rotar la clau al dashboard i tornar a desplegar el nou secret. És deliberat: minimitza la finestra d'exposició.

Política de rotació

Les API keys i els secrets de client OAuth són credencials de llarga vida i s'han de rotar en un calendari i de seguida després de qualsevol sospita de filtració.

  • Els prefixos són la font de veritat de l'entorn: fact_live_ (producció) i fact_test_ (sandbox). No els barregis mai entre entorns.
  • Rota des del dashboard (o mitjançant els endpoints self-service account:write) per emetre un secret nou. El nou secret es retorna una sola vegada — desa'l de seguida, no es torna a mostrar.
  • Finestra de gràcia (doble secret). Després d'una rotació el secret anterior continua funcionant durant una finestra de gràcia de 24 hores, perquè puguis desplegar el nou secret sense temps d'inactivitat. Durant aquesta finestra s'accepten tant el nou com l'anterior; en expirar la finestra el secret anterior es rebutja i es purga. Un request que continuï usant el secret anterior rep un header 199 Warning que indica quantes hores queden abans que deixi de funcionar.
  • Quan rotar: en un calendari regular (p. ex. cada 90 dies), sempre que un membre de l'equip amb accés marxi, i immediatament si un secret queda exposat alguna vegada en logs, control de versions o un client públic.
  • Revoca per invalidar una clau permanentment. Qualsevol request posterior amb ella falla amb 401. La revocació no té finestra de gràcia — és instantània i irreversible.

Els secrets estan lligats a una sola empresa (tenant) i no han d'incrustar-se mai en navegadors, apps mòbils ni cap client públic — mantén-los només al servidor.

Llista d'accés per IP

Cada API key es pot restringir a una llista d'IPs o rangs CIDR des del dashboard. Si el request arriba des d'una IP fora de la llista d'accés, la resposta és 401 i l'incident es registra al log d'auditoria. Deixa la llista d'accés buida per permetre qualsevol IP.

Errors d'autenticació

Les fallades relacionades amb l'API key responen amb HTTP 401 (o 403 per a insufficient_scope) i l'embolcall d'error estàndard. El camp code distingeix el cas:

codeHTTPCausa
missing_api_key401No s'ha enviat cap capçalera d'autenticació.
invalid_api_key401La clau no existeix, té un format incorrecte o el secret no coincideix amb el hash emmagatzemat.
api_key_revoked401La clau va ser revocada o ha caducat. Crea'n una de nova al dashboard.
too_many_auth_failures429Massa intents d'autenticació fallits; espera abans de reintentar.
insufficient_scope403La clau no té el scope que requereix l'endpoint.

Cada resposta inclou un request_id únic (també a la capçalera X-Request-Id) que pots facilitar a suport en 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"
  }
}

Bones pràctiques

  • Mai pugis API keys a repositoris — usa variables d'entorn o un gestor de secrets (AWS Secrets Manager, Doppler, 1Password Service Accounts).
  • Crea una clau per integració: facilita rotar i auditar l'accés sense afectar la resta.
  • Limita els scopes al mínim necessari. Un script d'exportació només necessita scopes :read concrets.
  • Activa la llista d'accés per IP per a integracions servidor a servidor amb IPs estables.
  • Configura expires_at per a claus temporals (p. ex. consultories, demos).
  • Audita l'ús des del dashboard: Developers > API Keys > Activity mostra IPs, rutes i errors per clau.

En aquesta pàgina