Create an invoice
Issue Verifactu invoices programmatically: payload anatomy, idempotency, and ready-to-run examples for every common tax situation.
GET /v1/invoices/{id} until verifactu.status leaves pending. The response is the full invoice object, including pdf_url and the Verifactu artifacts.
Three things follow from invoices being legal documents:
- They cannot be backdated or edited. There is no
invoice_datefield and no update endpoint. A wrong invoice is corrected with a rectificativa, never by mutation. To record that the operation happened before the issue date, useoperation_date. - Always send an
Idempotency-Key. A network timeout without one can issue a duplicate that you can only undo with a corrective invoice. With the header, retrying the exact same request replays the original response instead of issuing twice. See Idempotency. The key is kept for 24 hours; for a replay that arrives later than that, also send anexternal_id. - Totals are computed server-side from
quantity,unit_amount(net cents) and the taxrate, with the same rounding the Finseed dashboard uses. Dry-run any payload withPOST /v1/invoices/validateto see the exact totals before issuing.
Complete or simplified
Sendtype: "complete" when the recipient is identified: the full recipient block is required and the tax id is validated against the census before anything is persisted when it is a Spanish NIF (checked against AEAT together with the name) or an EU VAT number (checked against VIES, number only); the other id types consult no external register. Send type: "simplified" for tickets without an identified recipient. It is capped at 3,000 EUR including tax, and its optional recipient block deliberately has no tax_id field.
On a complete recipient, tax_id_type and tax_id_country may both be omitted: they are auto-detected from the tax_id format and the address country. When you do send tax_id_type, the country may still be omitted if the type implies it (es_nif and not_registered imply ES; eu_vat derives it from the VAT prefix), while passport, official_document, residence_certificate and other require an explicit tax_id_country. A pair that contradicts itself, such as es_nif with a non-ES country, is rejected with tax_id_type_country_mismatch.
Operation date
The issue date is always stamped server-side, but the operation itself may have happened earlier: an invoice issued in July for goods delivered in June. Send the optionaloperation_date (YYYY-MM-DD, a calendar day in the Europe/Madrid timezone) to record it. It must be between 2025-01-01 and today. When omitted it equals the issue date, and it is reported to the tax agency only when the two differ. It is not available on rectificativas.
Deduplicate with an external id
Idempotency-Key protects a retry for 24 hours. When your own system can re-send the same invoice later than that, for example a queue that replays a job days later or a nightly sync that reprocesses an order, send external_id with your own reference for the invoice, typically your order id. It is stored on the invoice and returned as external_id.
The value is unique within the environment: a second creation carrying it is rejected with external_id_already_used regardless of the idempotency key, the request body or how much time has passed, and the error’s detail names the invoice that holds it. A used value stays taken even if that invoice is later voided. To issue a genuinely new invoice for the same order, send a new value, for example order-84312-2. Any string of 1 to 255 characters without control characters is accepted, and POST /v1/invoices/validate applies the same check.
Examples
Standard domestic sale at 21% VAT:After the 201
The invoice exists and is legally issued the moment you receive the response. Two things are still settling in the background:- AEAT registration:
verifactu.statusstarts atpending(test environments answerregisteredimmediately and never contact AEAT). Poll the invoice until it becomesregistered, or handleregistered_with_errors/rejectedusingverifactu.error. - The PDF:
pdf_urlis valid immediately; if the PDF has not been rendered yet, the first download simply takes a moment longer.
Autorizaciones
API key sent as a bearer token in the Authorization header.
Encabezados
Optional key that makes the request safe to retry: 1 to 255 printable ASCII characters. Sending the same key with the same body within 24 hours returns the stored response instead of executing again; such a replay carries an Idempotent-Replayed: true header. Reusing a key with a different body is rejected.
Cuerpo
The invoice to issue.
- Option 1
- Option 2
The invoice to issue. The invoice number, issue date and totals are assigned server-side; the optional operation_date is the only date the caller sets. Issuance is immediate and the AEAT registration progresses asynchronously (poll verifactu.status). Include a rectifies block to issue a rectificativa instead of an ordinary invoice.
The lines to bill. At least one.
1 - 500 elementsA complete invoice: the recipient is identified and their tax id is validated against the census when it is a Spanish NIF or an EU VAT number. On a linked rectificativa (a rectifies.invoice_id) of a complete original, the recipient is inherited from the corrected invoice and may be omitted; when supplied on a substitution it restates the recipient. On a linked rectificativa type must match the corrected invoice: complete over a simplified original is refused with upgrade_to_complete_not_allowed, and simplified over a complete original with downgrade_to_simplified_not_allowed.
"complete"Your own reference for this invoice, such as an order id: 1 to 255 characters, no control characters. Unique per environment: a later request carrying the same value is rejected with external_id_already_used no matter how old the original is, which is the guard against duplicates that the 24-hour Idempotency-Key window cannot give. Once used, a value stays taken even after the invoice is voided. Echoed as external_id on the invoice.
1 - 255^[^\p{Cc}]{1,255}$"order-84312"
Number series to issue on (see the Number Series resource). Defaults to the environment default series. For an ordinary invoice this must be a standard series; for a rectificativa (a rectifies block) it must be a rectifying series. Rejected with num_series_not_applicable_for_order_invoice on a linked rectificativa against an order-linked invoice, which always numbers on the rectifying series its integration owns for that kind of correction.
"ns_clx456def789"
Turns this request into a rectificativa (corrective invoice). Reference the original with exactly one of invoice_id (issued through Finseed) or external (issued elsewhere). Omit the whole block to issue an ordinary invoice.
Date the underlying operation took place, as a calendar day (YYYY-MM-DD) interpreted in the Europe/Madrid timezone. Must be an existing calendar day between 2025-01-01 and today. When omitted, or when it equals the issue date, the invoice carries the issue date as its operation date. Not supported together with a rectifies block.
^(\d{4})-(\d{2})-(\d{2})$"2025-06-15"
Applies the Spanish recargo de equivalencia regime: every VAT line gains its legally paired surcharge (21%→5.2%, 10%→1.4%, 4%→0.5%), computed server-side.
false
Free-form text printed at the bottom of the invoice PDF.
2000"Pago a 30 días."
The identified recipient of a complete invoice.
Respuesta
The issued invoice.
A tax invoice as exposed by the public API.
Opaque, prefixed invoice identifier.
"inv_clx123abc456"
Lifecycle status of the invoice. This is an extensible enum: new values may be added in the future, so clients must tolerate values not listed here. Known values: issued, voided.
"issued"
Human-readable invoice number.
"2026-000123"
Lowercase ISO 4217 currency code.
"eur"
Net total before tax, in minor units (cents) of the currency.
8300
Total tax, in minor units (cents) of the currency.
1743
Gross total including tax, in minor units (cents) of the currency. Always equals subtotal + tax.
10043
Fiscal name of the invoice recipient (company or person), or null when none is recorded.
"ACME, S.L."
Tax identifier of the recipient (e.g. NIF/CIF), or null when none is recorded.
"B12345678"
Recipient email, or null when none is recorded.
Customer identifier from the originating integration, or null when unavailable.
"cus_9aZ"
The external_id supplied when the invoice was created through the API, or null when none was given.
"order-84312"
Invoice issue date, RFC 3339 in UTC.
"2026-06-01T09:30:00Z"
Date the underlying operation took place, RFC 3339 in UTC. Often equal to invoice_date.
"2026-06-01T09:30:00Z"
Creation timestamp, RFC 3339 in UTC.
"2026-06-01T09:30:00Z"
Whether this is a complete invoice (identified recipient) or a simplified invoice (ticket). This is an extensible enum: new values may be added in the future, so clients must tolerate values not listed here. Known values: complete, simplified.
"complete"
Identifier of the number series the invoice was issued on. See the Number Series resource.
"ns_clx456def789"
Full recipient block as recorded on the document, or null when no recipient data exists (simplified invoices). The flat recipient_name/recipient_tax_id/email fields remain as convenience aliases.
Signed link to the invoice PDF, valid for at least 24 hours from the moment this response was produced. Fetch a fresh one anytime by re-reading the invoice, or use the download endpoint. The PDF is generated shortly after creation; downloading earlier just takes a moment longer.
"https://api.finseed.es/v1/invoices/inv_clx123abc456/file?token=..."
Verifactu artifacts and AEAT registration state. Null only for legacy invoices imported before Verifactu tracking existed.
The lines that make up the invoice.
Whether this is an original invoice, a rectifying (corrective) one and by which method, or an exchange invoice. rectifying_differences corrects by the delta; rectifying_substitution replaces the original in full; exchange is the complete invoice issued in exchange for one or more correct simplified invoices (AEAT type F3), which stay valid and are not corrected. This is an extensible enum: new values may be added in the future, so clients must tolerate values not listed here. Known values: original, rectifying_differences, rectifying_substitution, exchange.
"original"
The invoices this invoice rectifies. Empty for originals. A rectificativa issued against invoices in Finseed carries one { invoice_id } entry per corrected invoice; one issued against an external original carries a single { external: { number, issued_on } } entry.
An invoice a rectificativa corrects: either a local invoice ({ invoice_id }) or an external original ({ external: { number, issued_on } }).
- Option 1
- Option 2
The rectifying invoices that correct this invoice, one { invoice_id } entry each. Empty when nothing rectifies it. Voided rectificativas are excluded.