Factuarea APIDevelopers

Resum dels SDKs

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.

Els SDK oficials de Factuarea ofereixen reintents automàtics, idempotència, paginació per cursor, errors tipats, verificació de webhooks i descàrregues binàries per al seu catàleg de mètodes publicat. REST exposa actualment 469 operacions en 41 recursos; consulta la cobertura de versions al final.

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 contacte amb rol de client i una factura, i descarrega’n el PDF amb els mètodes publicats de l’SDK que apareixen a continuació. Per a altres operacions, comprova l’SDK instal·lat o fes servir l’exemple HTTP de la referència de l’API.

La creació del contacte en PHP fa servir HTTP amb Guzzle, que el SDK PHP ja requereix. Així funciona sense assumir que la versió PHP instal·lada té mètodes de contactes generats. El SDK de factures conserva clientId: passa l’id del contacte amb rol customer actiu.

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 customer contact.
const { data: contact } = await factuarea.contacts.create({
  name: "Cliente Demo SL",
  kind: "company",
  roles: ["customer"],
  tax_id: "B12345674",
});

// 2. Create an invoice (the API computes the totals).
const { data: invoice } = await factuarea.invoices.create({
  client_id: contact.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 customer contact.
$http = new \GuzzleHttp\Client();
$response = $http->post('https://api.factuarea.com/v1/contacts', [
    'headers' => [
        'Authorization' => 'Bearer ' . getenv('FACTUAREA_API_KEY'),
        'Idempotency-Key' => bin2hex(random_bytes(16)),
    ],
    'json' => [
        'name' => 'Cliente Demo SL',
        'kind' => 'company',
        'roles' => ['customer'],
        'tax_id' => 'B12345674',
    ],
]);
$contact = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR)['data'];

// 2. Create an invoice (the API computes the totals).
$invoice = $factuarea->invoices->publicApiV1InvoicesCreate(
    new Components\CreateInvoiceRequest(
        clientId: $contact['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 ofereix exemples HTTP en TypeScript, PHP i cURL generats des del contracte OpenAPI documentat. Cobreixen la petició, les capçaleres necessàries i el format de resposta sense dependre de la cobertura d’una versió de l’SDK.

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.

Consulta el contracte OpenAPI documentat, exportat del backend i versionat amb aquest portal.

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.

Cobertura de les versions

La referència de setembre de 2026 és 0.2.0 per a tots dos SDK. Els specs de les seves branques principals contenen 413 entrades i encara els falten 39 endpoints REST. Cal actualitzar el paquet per disposar de nous mètodes generats. La referència de l’API ofereix exemples HTTP complets amb fetch de TypeScript, cURL de PHP i terminal per al contracte documentat; aquests exemples no pressuposen que existeixi cap mètode de l’SDK.

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport