Factuarea API

Scope and limitations

What the Factuarea API deliberately does not do, what it does not do yet, and the equivalent way to get each job done — plus four capabilities you may assume are missing and are not.

Every platform has boundaries. A boundary you can read before you integrate is a design decision; one you discover in production is a defect. This page is the single canonical list — no other guide keeps its own.

Each row states the scenario, its status, and the workaround: the alternative available today, or an explicit statement that there is none. There are exactly two statuses, because a third fuzzy category is what turns pages like this into wallpaper:

  • By design — we will not build it. The alternative is here.
  • On the roadmap — deferred, not rejected.

Verified on 31 July 2026 against v1 of the API. A row whose scenario becomes supported is removed in the same change that implements it, rather than left standing as an obsolete limitation.

Limitations verified against the code

ScenarioStatusWorkaround
Self-billing — the recipient issues the invoice in the supplier's nameBy designNot modelled. The supplier issues their own invoice. If you operate both parties, issue it from the supplier's account.
Invoice issued by a third partyBy designThe AEAT third-party-issuer field is not emitted. An agency operating a client's account issues from that account with X-Active-Profile; the invoice is declared as issued by the company itself.
Multi-currencyBy designThe v1 contract exposes euro, fixed: currency is always EUR and there is no currency column. Filtering a listing by any other currency returns an empty page, not an error. Invoice in euro and convert outside Factuarea.
TicketBAI / Batuz (Basque Country)By designNo alternative within Factuarea. The Basque provincial systems use different schemas, certificates and endpoints, and require their own certified software. Companies with a Basque tax domicile are warned during onboarding.
Reverse charge, and any header operation regime, declared over the APIBy designThe header operation_regime is read-only in v1 — neither create nor update accepts it — so every invoice created through the API is born under the general regime and qualifies S1. Exemption and non-subjection are declared per line with lines[].exemption_reason, but reverse charge is qualification S2 and has no line-level equivalent: issue those invoices from the dashboard. See International customers.
Disbursements outside the issued invoice — quotes, pro-formas, delivery notes, purchase invoices, recurring templatesBy designOnly the issued invoice models disbursements. Include the amount as an ordinary line in the preceding document, and set line_type on the resulting invoice while it is still a draft — the update operation accepts it.
Disbursements in the Facturae and UBL XML — the amount to pay in the XML is the fiscal total, not the amount dueOn the roadmapTaxable base and tax amounts are correct — the disbursement is properly excluded — but the payable amount falls short by it, and no element of the XML carries the difference. Do not route an invoice carrying disbursement lines through FACe until the native Facturae 3.2.2 block is mapped: invoice the disbursement outside that channel.
Disbursements in the aggregate portfolio figures — the pending_amount of GET /v1/invoices/stats, ageing and top-debtor reportsBy designThose aggregates measure invoiced volume, the same magnitude the annual third-party return declares, and have never subtracted partial payments either. For the amount actually owed, read pending_amount on each invoice, which does measure against the payable amount.

Deliberate differences from other platforms

These are conscious product decisions, not gaps. Each one exists because the alternative we chose is better for integrators than the pattern being asked for.

ScenarioStatusWorkaround
Offset pagination with a page count and jump-to-page-NBy designStripe-style cursor pagination: limit with validated bounds, plus starting_after or ending_before (mutually exclusive). Responses carry has_more and next_cursor, and next_cursor is null when has_more is false. See Pagination.
Permanently dual error envelope — our envelope and RFC 9457 in the same body, alwaysBy designContent negotiation. Accept: application/problem+json returns pure RFC 9457; anything else — application/json, */*, no Accept header — returns our envelope. See Errors.
Total atomicity in bulk create — one bad row rejects the batchBy designPartial success. The response carries {dry_run, total, successful, failed, results, failures}, where each failure identifies its row by zero-based index with its own error code. Import 480 of 500 and fix the 20. See Bulk operations.
Mandatory line totals in the request (line_total, taxable_base)By designline_total is an optional verified checksum: compared against the computed total with a one-cent tolerance, then discarded — never persisted, never returned. You do not have to replicate our calculation engine. See Disbursements.
Representation or power of attorney for third parties — proxy endpoints, signed authorisation documentsBy designEach company uploads its own certificate, which must match its own tax ID, is validated by structure and size, and whose passphrase is stored encrypted.
Substituting simplified invoices in two steps — a corrective plus a new complete invoiceBy designOne native step: POST /v1/invoices/substitute-simplified issues the substitute invoice aggregating several simplified ones. See Simplified or full invoices.
Python SDKOn the roadmapGenerate a client from the published OpenAPI document, or use the TypeScript or PHP SDKs, the CLI or the MCP server.

Capabilities you may assume are missing

Four things Factuarea does that integrators arriving from other platforms routinely expect not to find:

CapabilityWhere
Substitute invoice for simplified ones, in a single call — aggregate several tickets into one complete invoice without a corrective firstSimplified or full invoices · POST /v1/invoices/substitute-simplified
Subsanación of rejected VeriFactu records, exposed in the public API — repair a refused declaration without annulling the invoiceVeriFactu record subsanación · POST /v1/verifactu/records/{id}/subsanar
Corrective by differences with a negative taxable base — the fiscally correct way to express a refundCorrective invoices
AEAT fiscal catalogue queryable over the API — indirect tax regimes, operation regimes, exemption causes with their LIVA article, withholding rates and the legal VAT-to-surcharge pairs, in three languagesRegime keys · GET /v1/tax-catalog

None of these is announced or in development: all four are live operations today.

Where the fiscal reasoning lives

This page lists boundaries. The guides that explain the rules behind them:

Traceability

This page documents the absence of behaviour, which no business rule can assert. Its rows are therefore anchored differently from the other fiscal guides: to a verified point in the code, to the decision recorded for the platform, or — where a business rule does exist — to that rule.

Limitations verified against the code:

RowAnchor
Self-billingNo such capability in the domain. The only occurrences of the concept are the invoice Factuarea issues to its own subscribers and the system-company check — neither is an API capability.
Invoice issued by a third partyThe AEAT third-party-issuer field is never emitted; no occurrence in the application code.
Multi-currencyInvoiceV1Resource returns the literal 'EUR', and the v1 read repository documents that any other currency yields an empty page.
TicketBAI / BatuzBR-VFC-019 — deliberately out of scope for the VeriFactu context.
Reverse charge over the APINo v1 request accepts operation_regime; the invoice resource returns it read-only. BR-VFC-029 derives the qualification from that header regime, and BR-INV-032 limits the line catalogue to exemption and non-subjection causes, with no S codes.
Disbursements outside the issued invoiceBR-INV-037 and the line-type value object, which declares that only the issued invoice models disbursements; BR-INV-040 for the simplified-invoice restriction.
Disbursements in the Facturae and UBL XMLThe warning edge case of BR-INV-042, which records that the payable amount of both documents is the fiscal total and that the native Facturae 3.2.2 block is not mapped yet.
Disbursements in the aggregate portfolio figuresThe edge case of BR-INV-045, which records that the aggregates measure invoiced volume and are deliberately left measuring it.

Deliberate differences: anchored to the shared HTTP components that implement the alternative — cursor pagination, the error content negotiator, the bulk partial-success resource — to BR-INV-044 for the optional line checksum, to BR-VFC-003, BR-VFC-004, BR-VFC-022 and BR-VFC-024 for company-owned certificates, and to BR-INV-015 and BR-INV-016 for the single-step substitution. The Python SDK row reflects a recorded decision to plan it separately once the specification stabilises: it is deferred, not rejected, which is why its status is On the roadmap and not By design.

Capabilities: each is anchored to the live route that materialises it — public-api.v1.invoices.substitute_simplified, public-api.v1.verifactu.records.subsanar and public-api.v1.tax-catalog.show — plus BR-VFC-033 for the negative taxable base and BR-TAX-028 for the fiscal catalogue.

On this page