Factuarea API
SDKs

Visió general

SDKs oficials de TypeScript i PHP per a l'API de Factuarea — instal·la @factuarea/sdk o factuarea/factuarea-php i obtén reintents, idempotència, paginació per cursor, errors tipats i verificació de webhooks de sèrie.

Factuarea ofereix SDKs oficials que envolten tota l'API REST v1 (234 operacions repartides en 17 recursos) amb un runtime premium perquè no hagis d'escriure HTTP a mà: reintents automàtics, idempotency keys automàtiques, auto‑paginació per cursor transparent, una jerarquia d'errors tipada, verificació de webhooks tipada i descàrregues binàries (PDF).

Pre‑GA (0.x). Tots dos SDKs estan a 0.x. La superfície pública de mètodes és estable i segueix el contracte de nomenclatura de mètodes del SDK, protegit per SemVer — però mentre estigui a 0.x, les versions minor poden incloure canvis incompatibles fins a 1.0.0, que coincideix amb la GA de l'API. Cada release fixa una Factuarea-Version i l'envia a cada request, de manera que el comportament de l'API es manté estable fins que actualitzes el SDK.

Només al servidor. La teva API key és un secret. No incloguis mai un SDK amb una clau live en un navegador, app mòbil o qualsevol client públic — fes servir el SDK des del teu backend.

Instal·lació

npm install @factuarea/sdk

Requereix Node 20 o superior. El SDK està construït sobre l'estàndard Web fetch, així que també funciona a Deno, Bun i Cloudflare Workers.

composer require factuarea/factuarea-php

Requereix PHP 8.2 o superior amb les extensions json i mbstring (totes dues incloses a les builds estàndard de PHP).

Autenticació i entorns

Passa la teva API key. El prefix de la clau selecciona l'entorn — no hi ha cap flag a part: una clau fact_test_… sempre s'executa contra el sandbox aïllat, i una clau fact_live_… contra producció.

import { Factuarea } from "@factuarea/sdk";

const factuarea = new Factuarea({ apiKey: process.env.FACTUAREA_API_KEY! });

factuarea.environment; // "test" or "live", derived from the key prefix

Configuració opcional:

new Factuarea({
  apiKey: "fact_live_…",                    // required
  baseUrl: "https://api.factuarea.com/v1",  // override for staging
  timeout: 60_000,                          // per-request ms (default 60s)
  maxRetries: 2,                            // attempts after the first try
  factuareaVersion: "2026-06-04",           // pinned API version header
  defaultHeaders: {},                       // extra headers on every request
});
<?php

require 'vendor/autoload.php';

use Factuarea\Sdk\Custom\FactuareaClient;

// The key prefix selects the environment:
//   fact_test_… → sandbox    fact_live_… → production
$factuarea = FactuareaClient::create(getenv('FACTUAREA_API_KEY'));

FactuareaClient::create() és el punt d'entrada recomanat: connecta l'autenticació Bearer i registra per tu el comportament automàtic de Idempotency-Key. Per a configuració avançada (client Guzzle personalitzat, política de reintents personalitzada, base URL de staging) el builder generat continua disponible:

use Factuarea\Sdk\Factuarea;
use Factuarea\Sdk\Models\Components\Security;

$factuarea = Factuarea::builder()
    ->setSecurity(new Security(bearerAuth: getenv('FACTUAREA_API_KEY')))
    ->setServerURL('https://api.factuarea.com/v1')
    ->build();

Inici ràpid

Crea un client i una factura, i després descarrega'n el PDF. Cada operació és accessible com a <resource>.<method> (TypeScript) o ->{resource}->publicApiV1{Resource}{Action} (PHP) seguint el contracte de nomenclatura — els snippets per endpoint de la referència de l'API mostren la crida exacta per a cada operació.

import { Factuarea } from "@factuarea/sdk";

const factuarea = new Factuarea({ apiKey: process.env.FACTUAREA_API_KEY! });

// Responses are the API's `{ data: … }` envelope — read the resource off `.data`.

// 1. Create a client.
const { data: client } = await factuarea.clients.create({
  name: "Cliente Demo SL",
  tax_id: "B98765432",
});

// 2. Create an invoice (the API computes the totals).
const { data: invoice } = await factuarea.invoices.create({
  client_id: client.id,
  series_id: "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0e",
  issued_on: "2026-06-05",
  due_on: "2026-07-05",
  lines: [
    {
      description: "Consultoría — junio 2026",
      quantity: 10,
      unit_price: 100,
      tax_rate_id: "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0f",
    },
  ],
});

// 3. Download the PDF (a BinaryResponse, not JSON).
const pdf = await factuarea.invoices.pdf(invoice.id);
await import("node:fs/promises").then((fs) =>
  fs.writeFile("invoice.pdf", pdf.toBuffer()),
);
<?php

require 'vendor/autoload.php';

use Factuarea\Sdk\Custom\FactuareaClient;
use Factuarea\Sdk\Models\Components;
use Brick\DateTime\LocalDate;

$factuarea = FactuareaClient::create(getenv('FACTUAREA_API_KEY'));

// 1. Create a client.
$client = $factuarea->clients->publicApiV1ClientsCreate(
    new Components\CreateClientRequest(
        name: 'Cliente Demo SL',
        taxId: 'B98765432',
    ),
);

// 2. Create an invoice (the API computes the totals).
$invoice = $factuarea->invoices->publicApiV1InvoicesCreate(
    new Components\CreateInvoiceRequest(
        clientId: $client->object->data->id,
        seriesId: '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0e',
        issuedOn: LocalDate::parse('2026-06-05'),
        dueOn: LocalDate::parse('2026-07-05'),
        lines: [
            new Components\CreateInvoiceRequestLine(
                description: 'Consultoría — junio 2026',
                quantity: 10,
                unitPrice: 100,
                taxRateId: '01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0f',
            ),
        ],
    ),
);

// 3. Download the PDF.
$pdf = $factuarea->invoices->publicApiV1InvoicesPdf($invoice->object->data->id);
file_put_contents('invoice.pdf', $pdf->bytes ?? '');

Executa-ho tot primer amb una clau fact_test_ — els efectes del sandbox (VeriFactu → AEAT, FACe, email, webhooks) estan desactivats. Quan el teu flux funcioni d'extrem a extrem, canvia el prefix a fact_live_. La superfície de l'API és idèntica en tots dos. Consulta Test mode & sandbox.

Funcions en temps d'execució

Tots dos SDKs comparteixen el mateix runtime escrit a mà sobre la superfície tipada generada:

  • Reintents automàtics — les fallades transitòries (429 i 5xx, a més d'errors de xarxa a TypeScript) es reintenten amb backoff exponencial i jitter, respectant el header Retry-After. Els errors de client deterministes (p. ex. validació 422) mai es reintenten.
  • Idempotència automàtica — cada mutació rep una Idempotency-Key generada perquè un request reintentat mai creï un recurs per duplicat. Sobreescriu-la per crida quan vulguis deduplicació a nivell d'app. Consulta Idempotency.
  • Auto‑paginació per cursor — els mètodes de llistat retornen un iterable que recorre totes les pàgines per tu, gestionant next_cursor / has_more. Consulta Paginar amb el SDK.
  • Errors tipats — l'embolcall d'error de l'API es mapeja a una jerarquia d'excepcions tipada que exposa code, type, request_id i status. La teva API key mai s'inclou en cap missatge d'error. Consulta Gestionar errors.
  • Verificació de webhooks — un verificador HMAC‑SHA256 de temps constant que respecta la finestra de gràcia de rotació de secret. Consulta Verificar webhooks.
  • Descàrregues binàries — els endpoints de PDF i de fitxers retornen una resposta binària que converteixes en un Buffer / stream, no JSON.

Paginació amb el SDK

Els mètodes de llistat retornen un Page, que és en si mateix un async iterable:

const page = await factuarea.invoices.list({ status: "paid", limit: 50 });

// (a) iterate every item across every page
for await (const invoice of page) {
  console.log(invoice.id);
}

// (b) page by page
page.data;                              // items on this page
page.hasMore;                           // boolean
page.nextCursor;                        // opaque cursor or null
const next = await page.getNextPage();  // Page | null

// (c) collect everything into an array
const all = await page.toArray();

El helper PageIterator transmet cada element a través de totes les pàgines sense gestió manual del cursor:

use Factuarea\Sdk\Custom\Pagination\PageIterator;
use Factuarea\Sdk\Models\Operations\PublicApiV1InvoicesListRequest;

$pages = new PageIterator(
    fn (?string $cursor) => $factuarea->invoices->publicApiV1InvoicesList(
        new PublicApiV1InvoicesListRequest(startingAfter: $cursor),
    )->rawResponse,
);

// items() yields each item as a decoded associative array.
foreach ($pages->items() as $invoice) {
    echo $invoice['id'], PHP_EOL;
}

Consulta Pagination per conèixer la semàntica de cursor subjacent.

Gestió d'errors

import {
  FactuareaError,
  ValidationError,
  RateLimitError,
} from "@factuarea/sdk";

try {
  await factuarea.invoices.create(body);
} catch (error) {
  if (error instanceof ValidationError) {
    console.error(error.fields);     // { tax_id: ["NIF inválido"], … }
  } else if (error instanceof RateLimitError) {
    console.error(error.retryAfter); // seconds to wait
  } else if (error instanceof FactuareaError) {
    console.error(error.code, error.requestId);
  }
}
use Factuarea\Sdk\Models\Errors\ErrorThrowable;

try {
    $factuarea->invoices->publicApiV1InvoicesCreate($body);
} catch (ErrorThrowable $e) {
    $error = $e->container->error;
    echo $error->type->value;  // e.g. "invalid_request_error"
    echo $error->code;         // e.g. "parameter_invalid"
    echo $error->param;        // e.g. "client_id"
    echo $error->requestId;    // quote this to support
}

Ramifica segons el code estable, mai segons el message en castellà orientat a persones. El catàleg complet és a Errors.

Verificació de webhooks

Passa el cos cru del request (no un objecte re‑serialitzat), el header Factuarea-Signature i el secret de l'endpoint:

import { Factuarea, WebhookSignatureError, SIGNATURE_HEADER } from "@factuarea/sdk";

const factuarea = new Factuarea({ apiKey: process.env.FACTUAREA_API_KEY! });

// Express, with express.raw({ type: "application/json" }) on the route:
app.post("/webhooks/factuarea", (req, res) => {
  try {
    const event = factuarea.webhooks.verify(
      req.body.toString("utf8"),
      req.headers[SIGNATURE_HEADER.toLowerCase()] as string,
      process.env.FACTUAREA_WEBHOOK_SECRET!,
    );
    if (event.type === "invoice.paid") { /* … */ }
    res.sendStatus(200);
  } catch (e) {
    if (e instanceof WebhookSignatureError) return res.sendStatus(400);
    throw e;
  }
});
use Factuarea\Sdk\Custom\Webhooks\WebhookVerifier;
use Factuarea\Sdk\Custom\Webhooks\WebhookSignatureException;

$verifier = new WebhookVerifier();
$rawBody = file_get_contents('php://input');
$signature = $_SERVER['HTTP_FACTUAREA_SIGNATURE'] ?? '';

try {
    $event = $verifier->verify($rawBody, $signature, getenv('FACTUAREA_WEBHOOK_SECRET'));
    // $event is the decoded, authenticated payload
} catch (WebhookSignatureException $e) {
    http_response_code(400);
}

La verificació fa servir HMAC‑SHA256 amb una comparació de temps constant i una tolerància de timestamp configurable (5 minuts per defecte) per rebutjar replays, i accepta totes dues firmes durant una finestra de gràcia de rotació de secret. Consulta Webhooks.

Snippets per endpoint

Cada pàgina de la referència de l'API mostra un snippet de TypeScript, PHP i cURL llest per copiar per a aquesta operació exacta, generat a partir del spec perquè mai es desviïn de la superfície real.

Genera el teu propi client

Si el teu llenguatge encara no està cobert, o prefereixes un client que tu controlis i desis al teu repo, el contracte canònic llegible per màquina és el spec OpenAPI 3.1 — apunta-hi qualsevol generador.

El spec viu a https://docs.factuarea.com/api/openapi. Es genera a partir del mateix backend que serveix l'API, així que mai es desvia de la superfície real.

npx openapi-typescript https://docs.factuarea.com/api/openapi \
  -o src/factuarea.d.ts
openapi-python-client generate \
  --url https://docs.factuarea.com/api/openapi
openapi-generator-cli generate \
  -i https://docs.factuarea.com/api/openapi \
  -g <language> -o ./factuarea-client

<language> pot ser qualsevol generador suportat — Go, Java, C#, Ruby, Rust i més.

Un client generat no inclourà el runtime del SDK oficial (reintents, idempotència, paginació, verificació de webhooks) — això ho connectes tu mateix seguint les guies de conceptes clau.

Construeixes amb un assistent d'IA?

Si vols que un agent d'IA operi Factuarea directament en lloc de generar codi de client, connecta'l al servidor MCP — l'API pública exposada com a tools, amb autenticació OAuth i per API key. Per a Claude Code, el plugin oficial factuarea-mcp ho configura en dues comandes.

En aquesta pàgina