Factuarea API

VeriFactu auto-submission

There is no "send to AEAT" button. Registration is created when the invoice leaves draft — this is the list of gates that decide whether it happens, and the only manual levers that exist afterwards.

Integrators arriving from other invoicing platforms look for the operation that submits an invoice to the tax authority, do not find it, and assume the feature is missing. It is not missing: submission is not a step you perform. The registration is created as a consequence of issuing the invoice, and transmitted by a background pipeline.

This page is the answer to "why hasn't my invoice reached the AEAT?", which is almost always one of the gates below rather than a failure.

When this applies

To every invoice that leaves draft for a company whose VeriFactu activation is effective. Concretely, the registration is created on the transition into sent — including invoices that are born already issued: correctives, F3 substitutes, recurring generations, and creations that pass status: sent directly.

The draft stage is deliberately outside the mechanism. A draft has no definitive number, no frozen recipient snapshot and no fiscal existence; nothing is declared for it.

The gates, in the order they are evaluated

Instance kill-switch. A global flag can disable VeriFactu for the whole installation. It is an emergency switch, never an activation: on its own it enables nothing.

Per-company activation. This is the one you control. It defaults to off for a newly created account — a fresh company does not register invoices until someone activates VeriFactu. Effective activation is instance AND company (BR-VFC-025).

Read it with GET /v1/verifactu/config: the enabled field is already the effective value, not the raw company flag.

Operating mode. With activation on, a company still chooses between transmitting and not transmitting. In no_verifactu mode the chained records are still generated and stored locally — the mode changes transmission, not chaining — and must be available for inspection, but nothing is sent in real time (BR-VFC-018, RD 1007/2023 art. 16).

Historical-import bypass. Invoices loaded through the bulk import of pre-adhesion history carry a transient flag that makes the VeriFactu handlers return without creating any record (BR-INV-011, BR-VFC-009). Without it, importing years of history would declare thousands of registrations with issue dates from before the company joined the system. The flag is forced by the importer and is not exposed on the ordinary creation endpoints — you cannot set it from the public API.

Active certificate. Signing needs the company's own FNMT certificate. If there is none, or it is expired, revoked, or its tax ID does not match the company's, creation of the registration fails with a business-rule error. Check has_active_certificate on the config endpoint before going live.

If all five pass, the record is created, chained, and queued for transmission. Whether the queue transmits automatically is itself an instance-level setting surfaced read-only as auto_transmit on the config endpoint.

What the API sends

Nothing you write. There is no request body for "submit", and no field on POST /v1/invoices that controls it. What you do control is when the invoice is issued, and everything follows from that:

Because the "create and issue in one call" path emits both a creation and an issue event, two handlers race to create the same registration. The command is idempotent by invoice: the second one detects the existing registration and silently no-ops, so exactly one record exists per invoice (BR-VFC-008). You do not need to de-duplicate on your side.

The one explicit escape hatch

There is an operation that forces the creation of a registration for an already-issued invoice: POST /v1/invoices/{id}/verifactu, scope verifactu:write. It creates the registration and enqueues its transmission, answering 201 with the new record.

It exists for the case where an invoice was issued while a gate was closed — a certificate that had not been uploaded yet, for instance — and you want the registration once the gate opens. It is not a re-send:

SituationAnswer
The invoice already has a registration422 verifactu_already_submitted
The invoice is still a draft, VeriFactu is disabled for the instance, or the certificate is missing, expired, revoked or has a mismatched tax ID422 verifactu_not_eligible
The invoice does not exist, or belongs to another company404 invoice_not_found
curl -X POST https://api.factuarea.com/v1/invoices/0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42/verifactu \
  -H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW"

The only manual levers on a record that already exists

Once the registration exists, exactly two operations act on it, and both are covered in VeriFactu submission states:

  • retry — re-sends the stored declaration unchanged, for technical failures.
  • subsanar — regenerates the declaration from corrected master data, for AEAT rejections.

There is no operation that re-transmits an accepted record. Acceptance is terminal by regulation.

Activation is a commitment, not a toggle

Turning VeriFactu on is asymmetric, and an integration that treats it as a reversible switch will hit a 422 in production.

Moving to the verifiable mode is always allowed. Moving back is blocked until 31 December of the year in which it was activated (BR-VFC-001, BR-VFC-023, RD 1007/2023 art. 13). The integrity of a chain declared to the AEAT in real time cannot be downgraded to self-certified software halfway through a tax year.

There is one deliberate escape: while the chain is still empty — the company has not emitted a single billing record in any state — the company may change its mind and go back, and the lock is cleared. The first record emitted, even a rejected or errored one, arms the lock until the end of the year. Turning off the per-company activation flag is blocked by the same guard, so it cannot be used to sidestep the commitment.

GET /v1/verifactu/config exposes is_locked_until so you can show this to your users before they commit.

Sandbox and production are not interchangeable

Each company operates against one AEAT environment, exposed as environment on both the config object and every record. A CSV obtained against the AEAT test bed is not a registration: test CSVs carry a recognisable prefix, and a production database containing them means something was simulated that should have been transmitted (BR-VFC-017).

The rule that protects you is that the system must never fall back to simulation silently — an unreachable endpoint has to surface as a technical error state, not as a fabricated acceptance. When you reconcile, treat the environment field as part of the record's identity.

What appears on the PDF

Auto-submission itself adds nothing to the document; the printed artefact depends on the existence of a record, not on how it was created. Once a record exists, the invoice carries the legal QR block (BR-VFC-015), and the legend under the code differs between the two operating modes: the short VERI*FACTU mark in verifiable mode, and the full sentence stating the invoice is verifiable at the AEAT electronic office in the other.

An invoice imported with the historical bypass has no record and therefore prints no QR. That is correct: pre-adhesion invoices are not verifiable at the AEAT.

What reaches the AEAT

One registration declaration per issued invoice, chained to the company's previous record, plus an annulment declaration if the invoice is later annulled (see Annul or correct). Nothing else is transmitted as a consequence of issuing.

In no_verifactu mode nothing reaches the AEAT in real time at all; the company keeps the local chain for inspection and the system periodically records summaries of its own operational events, which the regulation treats as separate evidence (BR-VFC-018).

Traceability

Derived from the domain rules of the Factuarea backend:

  • BR-VFC-001 — adhesion to the verifiable mode is irrevocable until the end of the calendar year, with the empty-chain exception.
  • BR-VFC-008 — idempotency: one registration per invoice, even when the create-and-issue flow fires two events.
  • BR-VFC-009 — the historical-import bypass, seen from the VeriFactu side.
  • BR-VFC-015 — the QR block and its two legends.
  • BR-VFC-017 — the sandbox/production boundary and the prohibition on silent simulation.
  • BR-VFC-018no_verifactu mode: local chain, event summaries, no real-time transmission.
  • BR-VFC-023 — the asymmetric mode switch and the year-end lock, including the guard that stops the activation flag from bypassing it.
  • BR-VFC-025 — per-company activation, default off, effective value as instance AND company.
  • BR-INV-011 — the historical-import bypass, seen from the invoicing side.

On this page