Skip to main content

Quick Start

Introduction

This tutorial runs entirely in the ES sandbox. You will authenticate, register a sandbox Legal Entity, send a Facturae 3.2.2 invoice, and obtain its VERI*FACTU QR.

Sandbox API URL: https://es-sandbox.api.acubeapi.com

No production credentials or real fiscal documents are used in this tutorial.

You will complete three steps:

  1. Get sandbox access and authenticate.
  2. Register a new Legal Entity.
  3. Send an invoice and read its QR.

1. Get sandbox access and authenticate

Create a free sandbox account. To receive an access token, follow the authentication guide.

If the token does not grant access to the ES API, contact A-Cube support.

A legal entity represents the Spanish taxpayer you issue invoices for. It is created directly — there is no external portal step.

Use POST /legal-entities. Replace {{jwt}} with the token from step 1. taxId must be a valid Spanish NIF, NIE or CIF (9 characters, format-checked).

POST /legal-entities
Authorization: Bearer {{jwt}}
Content-Type: application/json
Accept: application/json

{
"taxId": "A58818501",
"name": "A-Cube Test Company",
"email": "test@acme.test",
"phoneNumber": "+34600000000",
"country": "ES",
"address": "Calle Mayor 1",
"city": "Madrid",
"stateOrProvince": "Madrid",
"zipCode": "28001",
"config": {
"supplierInvoiceEnabled": true,
"customerInvoiceEnabled": true
}
}
{
"uuid": "01a047df-a310-75f9-8176-b9370c82a850",
"taxId": "A58818501",
"name": "A-Cube Test Company",
"status": "legal_entity.onboarding_completed",
"config": { "supplierInvoiceEnabled": true, "customerInvoiceEnabled": true },
"createdAt": "2026-08-28T10:17:13+00:00",
"updatedAt": null
}

customerInvoiceEnabled must be true for the entity to issue invoices. Save the uuid and the taxId — you will use the tax id as the invoice sender.

3. Send an invoice

3.1 Send a Facturae 3.2.2 invoice

Prepare a valid Facturae document whose SellerParty tax id is the taxId of the legal entity you just registered, and post it to POST /invoices. The example below uses XML; you can send the equivalent JSON with Content-Type: application/json instead.

POST /invoices
Authorization: Bearer {{jwt}}
Content-Type: application/xml
Accept: application/json
<?xml version="1.0" encoding="UTF-8"?>
<fe:Facturae xmlns:fe="http://www.facturae.gob.es/formato/Versiones/Facturaev3_2_2.xml" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<FileHeader>
<SchemaVersion>3.2.2</SchemaVersion>
<Modality>I</Modality>
<InvoiceIssuerType>EM</InvoiceIssuerType>
<Batch>
<BatchIdentifier>A58818501-FV-2026-0001</BatchIdentifier>
<InvoicesCount>1</InvoicesCount>
<TotalInvoicesAmount><TotalAmount>1452.00</TotalAmount></TotalInvoicesAmount>
<TotalOutstandingAmount><TotalAmount>1452.00</TotalAmount></TotalOutstandingAmount>
<TotalExecutableAmount><TotalAmount>1452.00</TotalAmount></TotalExecutableAmount>
<InvoiceCurrencyCode>EUR</InvoiceCurrencyCode>
</Batch>
</FileHeader>
<Parties>
<SellerParty>
<TaxIdentification>
<PersonTypeCode>J</PersonTypeCode>
<ResidenceTypeCode>R</ResidenceTypeCode>
<TaxIdentificationNumber>A58818501</TaxIdentificationNumber>
</TaxIdentification>
<LegalEntity>
<CorporateName>SupplierOfficialName Ltd.</CorporateName>
<AddressInSpain>
<Address>Calle Mayor 1</Address>
<PostCode>28001</PostCode>
<Town>Madrid</Town>
<Province>Madrid</Province>
<CountryCode>ESP</CountryCode>
</AddressInSpain>
</LegalEntity>
</SellerParty>
<BuyerParty>
<TaxIdentification>
<PersonTypeCode>J</PersonTypeCode>
<ResidenceTypeCode>R</ResidenceTypeCode>
<TaxIdentificationNumber>B12345674</TaxIdentificationNumber>
</TaxIdentification>
<LegalEntity>
<CorporateName>Buyer Official Name</CorporateName>
<AddressInSpain>
<Address>Calle Alcala 20</Address>
<PostCode>28014</PostCode>
<Town>Madrid</Town>
<Province>Madrid</Province>
<CountryCode>ESP</CountryCode>
</AddressInSpain>
</LegalEntity>
</BuyerParty>
</Parties>
<Invoices>
<Invoice>
<InvoiceHeader>
<InvoiceNumber>FV-2026-0001</InvoiceNumber>
<InvoiceDocumentType>FC</InvoiceDocumentType>
<InvoiceClass>OO</InvoiceClass>
</InvoiceHeader>
<InvoiceIssueData>
<IssueDate>2026-01-15</IssueDate>
<InvoiceCurrencyCode>EUR</InvoiceCurrencyCode>
<TaxCurrencyCode>EUR</TaxCurrencyCode>
<LanguageName>es</LanguageName>
</InvoiceIssueData>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
<TaxRate>21.00</TaxRate>
<TaxableBase><TotalAmount>1200.00</TotalAmount></TaxableBase>
<TaxAmount><TotalAmount>252.00</TotalAmount></TaxAmount>
</Tax>
</TaxesOutputs>
<InvoiceTotals>
<TotalGrossAmount>1200.00</TotalGrossAmount>
<TotalGrossAmountBeforeTaxes>1200.00</TotalGrossAmountBeforeTaxes>
<TotalTaxOutputs>252.00</TotalTaxOutputs>
<TotalTaxesWithheld>0.00</TotalTaxesWithheld>
<InvoiceTotal>1452.00</InvoiceTotal>
<TotalOutstandingAmount>1452.00</TotalOutstandingAmount>
<TotalExecutableAmount>1452.00</TotalExecutableAmount>
</InvoiceTotals>
<Items>
<InvoiceLine>
<ItemDescription>Servicios de consultoria</ItemDescription>
<Quantity>1</Quantity>
<UnitPriceWithoutTax>1200.00</UnitPriceWithoutTax>
<TotalCost>1200.00</TotalCost>
<GrossAmount>1200.00</GrossAmount>
<TaxesOutputs>
<Tax>
<TaxTypeCode>01</TaxTypeCode>
<TaxRate>21.00</TaxRate>
<TaxableBase><TotalAmount>1200.00</TotalAmount></TaxableBase>
<TaxAmount><TotalAmount>252.00</TotalAmount></TaxAmount>
</Tax>
</TaxesOutputs>
</InvoiceLine>
</Items>
<PaymentDetails>
<Installment>
<InstallmentDueDate>2026-02-14</InstallmentDueDate>
<InstallmentAmount>1452.00</InstallmentAmount>
<PaymentMeans>04</PaymentMeans>
</Installment>
</PaymentDetails>
</Invoice>
</Invoices>
</fe:Facturae>
{
"uuid": "01a03e4a-ee3a-7e1f-b372-c8382bd4ec73",
"invoiceNumber": "FV-2026-0001",
"invoiceDate": "2026-01-15",
"dueDate": "2026-02-14",
"currency": "EUR",
"totalAmount": "1452.00",
"netAmount": "1200.00",
"direction": "outgoing",
"sender": { "name": "SupplierOfficialName Ltd.", "fiscalId": "A58818501" },
"recipient": { "name": "Buyer Official Name", "fiscalId": "B12345674" },
"status": "accepted",
"errorReason": null,
"downloaded": false,
"downloadedAt": null
}
tip

To test your error handling, set the BuyerParty tax id to one of the reserved sandbox values (for example ESSANDBOXERR0002 for a duplicate-number rejection).

3.2 Read the VERI*FACTU QR

GET /invoices/01a03e4a-ee3a-7e1f-b372-c8382bd4ec73/qr
Authorization: Bearer {{jwt}}
Accept: application/json
{
"url": "https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR?nif=A58818501&numserie=FV-2026-0001&fecha=15-01-2026&importe=1452.00",
"nif": "A58818501",
"seriesNumber": "FV-2026-0001",
"issueDate": "15-01-2026",
"totalAmount": "1452.00"
}

Request it with Accept: image/png to get the QR as an image. See VERI*FACTU QR.

3.3 (Optional) Build it as a draft first

Instead of sending in one shot, you can POST /invoices/draft with partial content (only Parties is required), refine it with PUT /invoices/draft/{uuid}, then POST /invoices/draft/{uuid}/send.

3.4 List your invoices

GET /invoices?direction=outgoing&order[invoiceDate]=desc
Authorization: Bearer {{jwt}}
Accept: application/json

See Search documents for the full filter set.

tip

You can now authenticate, register a sandbox entity, and issue a Facturae invoice with its VERI*FACTU QR.