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, with 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, since 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.