Special VAT Regimes (REDE / Simplificado)
Special tax regimes (recargo de equivalencia / REDE and Simplificado) are officially supported for VAT regions starting with EFR version 2.11.0.
Special tax regimes (recargo de equivalencia / REDE and Simplificado) are currently in Pilot phase. Please contact your efsta partner manager if you would like to participate.
Spanish VAT law knows special regimes next to the general one. Two of them are relevant for the EFR API, and they are independent of each other:
| Case | What it describes | How you send it |
|---|---|---|
| Own tax regime | You (the invoice issuer) operate under the simplified regime or under REDE yourself. | VatRegime field |
| Recargo de equivalencia | You sell to a retailer who is under the REDE regime, so your invoice has to carry the equivalence surcharge (recargo) next to the VAT. | Surcharge tax group pair in Pos.TaxG, e.g. "R1 S1" |
These two cases are mutually exclusive on one line: a REDE retailer charges no recargo on its
own sales, so a surcharge line combined with VatRegime="REDE" is rejected. See
Validation rules.
Overview
Everything on this page connects to one question the EFR answers for every position: which regime applies to this line, and does it carry a surcharge?
- You declare the regimes — How to set the regimes describes the
two inputs: your own regime is set via
VatRegime(usually once, in the company configuration), and a sale to a REDE retailer is marked per position with a surcharge tax group pair such asTaxG="R1 S1". - The EFR computes and reports — How the regimes work describes what is derived from those inputs: the tax breakdown with net, VAT and surcharge amounts, the regime code each line reports to the fiscal authority, how mixed-regime documents are split, and the province differences that are handled automatically.
- Additional data and validation — TicketBAI requires an identified customer for surcharge sales, and the validation rules list every combination that is rejected.
A typical integration therefore only needs two things: set VatRegime once if the
merchant is under the simplified or REDE regime, and send the surcharge pair on positions sold to
REDE retailers. Everything else — amounts, regime codes, province handling — is derived by the
EFR.
Availability
| Region | Recargo (R*/S*) | VatRegime |
|---|---|---|
| VERI*FACTU (mainland) | yes | yes |
| TicketBAI (Araba, Bizkaia, Gipuzkoa) | yes, national recipient required | yes, issuer restrictions |
| VERI*FACTU IGIC (Canary Islands) | no | no |
The special regimes are IVA-only concepts. Sending either of them for the Canary Islands is
rejected with #TAXG_NV.
How to Set the Regimes
Your Own Regime: VatRegime
VatRegime declares your own (the issuer's) tax regime. It is optional and drives
the regime code reported to the fiscal authority.
Values
| Value | Meaning |
|---|---|
GENERAL | Régimen general del IVA — standard VAT regime |
SIMPLE | Régimen simplificado — simplified VAT regime |
REDE | Recargo de equivalencia — retail trade regime; own invoices carry no surcharge |
Any other non-empty value is rejected with #INVALID. An empty string or an absent field counts
as not set.
Where to set it
The field can be set on three levels:
| Level | Field | How to set |
|---|---|---|
| Company | Cfg.Cmp.VatRegime | Tax Regime dropdown in the Base config UI page, or POST /cfg with {"Cfg":{"Cmp":{"VatRegime":"REDE"}}} |
| Transaction | ESR.VatRegime | API only |
| Position | ESR.PosA[].VatRegime | API only |
Precedence is position (PosA) > transaction (ESR) > company (Cmp).
An empty value never shadows a lower level; if
the field is not set anywhere, the regime resolves to GENERAL.
Most integrations set the regime once in the company configuration. The transaction and position levels exist for mixed documents.
Selling to a REDE Retailer: Surcharge Tax Groups
The surcharge is expressed as a pair of tax groups on the position: a dedicated REDE VAT group
(R1–R4) plus its surcharge group (S1–S4), delimited by a space — the same mechanism as
described in Tax Group Assignment.
Pos.TaxG | VAT group | VAT rate | Surcharge group | Surcharge rate | Use |
|---|---|---|---|---|---|
"R1 S1" | R1 | 21% | S1 | 5.2% | Standard rate |
"R2 S2" | R2 | 10% | S2 | 1.4% | Lower rate |
"R3 S3" | R3 | 4% | S3 | 0.5% | Reduced rate |
"R4 S4" | R4 | 21% | S4 | 1.75% | Tobacco products |
Each pair is fixed. The R* group and the S* group must always be sent together, and only in
the combinations above.
The surcharge pair and VatRegime are independent: a merchant under the general or
simplified regime can sell to REDE retailers, so a surcharge pair may appear on GENERAL and
SIMPLE lines. Only a line resolving to VatRegime="REDE" must not carry one — see
Validation rules.
Position amount
Pos.Amt is the gross amount including both VAT and the surcharge. The EFR derives the
breakdown from it: the surcharge is stripped first, and the remainder is split into net and VAT.
For "TaxG": "R1 S1" with "Amt": "5.00" (21% + 5.2%) the breakdown is:
| Value | Amount |
|---|---|
| Taxable base | 3.96 |
| VAT 21% | 0.83 |
| Surcharge 5.2% of 3.96 | 0.21 |
| Position total | 5.00 |
A single position sold to a REDE retailer
- XML
- JSON
<Tra>
<ESR TL="001" TT="1" T="5.00">
<PosA>
<Pos PN="1" Dsc="Wholesale item" TaxG="R1 S1" Amt="5.00" />
</PosA>
<PayA>
<Pay Dsc="Example Payment" PayG="cash" Amt="5.00" />
</PayA>
</ESR>
</Tra>
{
"Tra": {
"ESR": {
"TL": "001",
"TT": "1",
"T": "5.00",
"PosA": [
{
"_": "Pos",
"PN": "1",
"Dsc": "Wholesale item",
"TaxG": "R1 S1",
"Amt": "5.00"
}
],
"PayA": [
{
"_": "Pay",
"Dsc": "Example Payment",
"PayG": "cash",
"Amt": "5.00"
}
]
}
}
}
For TicketBAI this request additionally needs an identified national recipient in ESR.Ctm —
see Customer data.
How the Regimes Work
Once the regimes are declared as described above, the EFR derives everything the fiscal authority needs: the tax breakdown including the surcharge amounts, the regime code per breakdown line, the splitting of mixed documents, and the province-specific reporting.
Tax Breakdown (TaxA)
ESR.TaxA is computed automatically if you only send positions. The surcharge element follows the same convention as the Croatian
consumption tax:
Tax.TTY="SVAT"marks the element as an equivalence surchargeTax.TaxGis the surcharge group (S1–S4)Tax.Prcis the surcharge percentageTax.Baseis the taxable base the surcharge is calculated on (equals theR*group'sNet).Tax.Amtis the surcharge amount, not a gross amountTax.NetandTax.TAmtare not set — they are also absent from the response
The surcharge amount is part of the transaction total: ESR.T equals the sum of all TaxA[].Amt,
including the SVAT elements.
Multiple items with surcharges and one without
- Two surcharge positions at different rates
- One ordinary position
- Customer object that also satisfies the TicketBAI requirements
- XML
- JSON
- Resulting tax breakdown
Request:
<Tra>
<ESR D="2026-07-06T10:00:00" TL="001" TT="1" T="11.00">
<Ctm Nam="Cliente Ejemplo" TaxId="ES87654321B" Adr="First street" Zip="44000" />
<PosA>
<Pos PN="1" Dsc="Item REDE 21%" TaxG="R1 S1" Amt="5.00" />
<Pos PN="2" Dsc="Item REDE 10%" TaxG="R2 S2" Amt="5.00" />
<Pos PN="3" Dsc="Item normal 21%" TaxG="A" Amt="1.00" />
</PosA>
<PayA>
<Pay Dsc="Example Payment" PayG="cash" Amt="11.00" />
</PayA>
</ESR>
</Tra>
Response:
<TraC>
<Result RC="OK"/>
<ESR D="2026-08-12T16:16:17" TN="47" FN="2026.1-001-1-47">
<TaxA>
<Tax TaxG="A" Prc="21" Net="0.83" TAmt="0.17" Amt="1.00"/>
<Tax TaxG="R1" Prc="21" Net="3.96" TAmt="0.83" Amt="4.79"/>
<Tax TaxG="R2" Prc="10" Net="4.49" TAmt="0.45" Amt="4.94"/>
<Tax TTY="SVAT" TaxG="S1" Prc="5.2" Base="3.96" Amt="0.21"/>
<Tax TTY="SVAT" TaxG="S2" Prc="1.4" Base="4.49" Amt="0.06"/>
</TaxA>
</ESR>
<Fis>
<Tag Label="" Value="*** TEST MODE ***" Name="Testmode"/>
<Tag Label="Factura" Value="2026.1-001-1-47" Name="FN"/>
<Tag Label="Código Seguro de Verificación" Value="A-LQVMKLYTEAPG4C" Name="CSV"/>
</Fis>
</TraC>
Request:
{
"Tra": {
"ESR": {
"D": "2026-07-06T10:00:00",
"TL": "001",
"TT": "1",
"T": "11.00",
"Ctm": {
"Nam": "Cliente Ejemplo",
"TaxId": "ES87654321B"
},
"PosA": [
{
"_": "Pos",
"PN": "1",
"Dsc": "Item REDE 21%",
"TaxG": "R1 S1",
"Amt": "5.00"
},
{
"_": "Pos",
"PN": "2",
"Dsc": "Item REDE 10%",
"TaxG": "R2 S2",
"Amt": "5.00"
},
{
"_": "Pos",
"PN": "3",
"Dsc": "Item normal 21%",
"TaxG": "A",
"Amt": "1.00"
}
],
"PayA": [
{
"_": "Pay",
"Dsc": "Example Payment",
"PayG": "cash",
"Amt": "11.00"
}
],
}
}
}
Response:
{
"TraC": {
"Result": {
"RC": "OK",
},
"ESR": {
"TN": "48",
"FN": "2026.1-001-1-48",
"TaxA": [
{
"_": "Tax",
"TaxG": "A",
"Prc": "21",
"Net": "0.83",
"TAmt": "0.17",
"Amt": "1.00"
},
{
"_": "Tax",
"TaxG": "R1",
"Prc": "21",
"Net": "3.96",
"TAmt": "0.83",
"Amt": "4.79"
},
{
"_": "Tax",
"TaxG": "R2",
"Prc": "10",
"Net": "4.49",
"TAmt": "0.45",
"Amt": "4.94"
},
{
"_": "Tax",
"TTY": "SVAT",
"TaxG": "S1",
"Prc": "5.2",
"Base": "3.96",
"Amt": "0.21"
},
{
"_": "Tax",
"TTY": "SVAT",
"TaxG": "S2",
"Prc": "1.4",
"Base": "4.49",
"Amt": "0.06"
}
]
},
"Fis": {
"Tag": [
{
"Label": "",
"Value": "*** TEST MODE ***",
"Name": "Testmode"
},
{
"Label": "Factura",
"Value": "2026.1-001-1-48",
"Name": "FN"
},
{
"Label": "Código Seguro de Verificación",
"Value": "A-J4UHL4Z792XVSP",
"Name": "CSV"
}
],
}
}
}
The returned TaxA echoes the tax groups with the computed values. The SVAT elements carry
Base and Amt only:
TaxG | TTY | Prc | Net | TAmt | Base | Amt |
|---|---|---|---|---|---|---|
| A | 21 | 0.83 | 0.17 | 1.00 | ||
| R1 | 21 | 3.96 | 0.83 | 4.79 | ||
| S1 | SVAT | 5.2 | 3.96 | 0.21 | ||
| R2 | 10 | 4.49 | 0.45 | 4.94 | ||
| S2 | SVAT | 1.4 | 4.49 | 0.06 |
Sum of all Amt values = 11.00 = ESR.T.
The fiscal response itself (TraC.Fis) is unchanged by the REDE feature — see
Response TraC.
Reported Regime Codes
Each breakdown line reports the regime resolved for its positions (see precedence):
| Resolved regime | VERI*FACTU ClaveRegimen | TicketBAI clave | Surcharge fields |
|---|---|---|---|
GENERAL (also the default) | 01 | 01 | emitted when the line carries an R*/S* pair |
SIMPLE | 20 | 52 | emitted when the line carries an R*/S* pair |
REDE | 18 | 51 | not allowed — see Validation rules |
Surcharge tax groups and the regime choice are independent: a GENERAL line with an R1 S1 pair
reports clave 01 and the surcharge amounts.
Mixed-Regime Transactions
Positions with different resolved regimes are reported as separate tax breakdown lines, even when they share the same tax rate. Each line's amounts are derived from its own positions.
Example
- XML
- JSON
<Tra>
<ESR TL="001" TT="1" T="2.00" VatRegime="SIMPLE">
<PosA>
<Pos PN="1" Dsc="Simplified item" TaxG="A" Amt="1.00" />
<Pos PN="2" Dsc="General item" TaxG="A" Amt="1.00" VatRegime="GENERAL" />
</PosA>
<PayA>
<Pay Dsc="Example Payment" PayG="cash" Amt="2.00" />
</PayA>
</ESR>
</Tra>
{
"Tra": {
"ESR": {
"TL": "001",
"TT": "1",
"T": "2.00",
"VatRegime": "SIMPLE",
"PosA": [
{
"_": "Pos",
"PN": "1",
"Dsc": "Simplified item",
"TaxG": "A",
"Amt": "1.00"
},
{
"_": "Pos",
"PN": "2",
"Dsc": "General item",
"TaxG": "A",
"Amt": "1.00",
"VatRegime": "GENERAL"
}
],
"PayA": [
{
"_": "Pay",
"Dsc": "Example Payment",
"PayG": "cash",
"Amt": "2.00"
}
]
}
}
}
Position 1 inherits SIMPLE from the transaction level, position 2 overrides it to GENERAL. The
document reports two 21% breakdown lines, one per regime.
Each breakdown line is rounded against its own positions, so in a mixed-regime document the
reported lines may drift from the aggregated totals by up to one cent per position. This drift is
tolerated — no warning is raised and the transaction is registered normally. Only a larger
deviation — e.g. an explicitly sent TaxA whose regime split does not reproduce the aggregate —
is rejected with a #DIFF error before anything is submitted to the authority. Single-regime
documents are not affected.
Province Differences (TicketBAI)
In TicketBAI, every non-exempt tax breakdown line carries the per-line flag
OperacionEnRecargoDeEquivalenciaORegimenSimplificado in the fiscal XML: S when the line's
resolved regime is SIMPLE or REDE, N otherwise — including surcharge lines sold under the
general regime. Exempt lines carry no flag.
Bizkaia accepts only the special claves in a mixed-regime document ("Las claves 51 y 52 sólo son
compatibles entre sí"), so clave 01 is dropped there and the per-line flag alone carries the
distinction. Araba and Gipuzkoa keep the full set of claves. This is handled automatically — the
request is identical for all three provinces.
Customer Data (Ctm)
The two fiscal systems treat the customer object (ESR.Ctm) in opposite ways: TicketBAI
requires it for surcharge sales, while VERI*FACTU accepts it only on invoices.
TicketBAI: National Recipient Required
The Basque provinces validate the recargo more strictly than AEAT. For TicketBAI only, a transaction containing a surcharge pair must identify a national recipient:
ESR.Ctmmust be present and must containCtm.TaxId- the recipient must be Spanish — a
TaxIdwith theESprefix,Ctm.Ctry="ES", or aTaxIdwithout a country prefix and noCtm.Ctryset - an
N-prefix NIF (non-resident entity) does not qualify
Otherwise the transaction is rejected with #REDE_CTM.
VERI*FACTU: Customer Data Only on Invoices
VERI*FACTU has no recipient requirement for surcharges — a surcharge transaction without
ESR.Ctm is accepted. Customer data is registered only for invoices (DT/NFS = "INVOICE").
If any other transaction — a simplified receipt, with or without REDE — contains ESR.Ctm, the
customer data is not reported to AEAT and the response carries a warning:
w-#CTM_ERR Not allowed to send Ctm data in non-invoice transactions
The transaction itself is still registered (RC="OK"). A request built to satisfy the TicketBAI
recipient requirement above is therefore also accepted by VERI*FACTU — the customer data is
simply dropped there, with the warning.
Validation Rules
| Rule | Error |
|---|---|
An S* surcharge group must not be sent alone | #TAXG_NV |
An R* VAT group must not be sent alone | #TAXG_NV |
A surcharge group must be paired with its own R* group ("A S1", "R1 S2" are invalid) | #TAXG_NV |
| A position must not combine more than one VAT group with one surcharge group | #TAXG_NV |
TaxPos positions do not support surcharge pairs | #TAXG_NV |
A surcharge pair must not be sent on a line resolving to VatRegime="REDE" | #TAXG_NV |
VatRegime and surcharge groups are not available for IGIC (Canary Islands) | #TAXG_NV |
VatRegime must be GENERAL, SIMPLE or REDE | #INVALID |
An SVAT element sent in ESR.TaxA must declare a numeric Base | #TAXG_NV |
| The declared rate must exist in the Spanish tax table | #TAXG_NF |
TicketBAI-only rules
These apply to the Basque provinces and have no VERI*FACTU counterpart:
| Rule | Error |
|---|---|
A surcharge pair requires an identified national recipient in ESR.Ctm | #REDE_CTM |
VatRegime="REDE" must not appear on a document that also carries a surcharge pair | #REDE_REGIME |
VatRegime="REDE" requires the issuer to be a natural person or an E/J-prefix entity (comunidad de bienes / sociedad civil) — a company CIF cannot use it | #REDE_ISSUER |
All of these reject the transaction (RC="BAD"). For the general error handling and the meaning of
result codes see TraC.Result.
Limitations
- Not available for the Canary Islands (IGIC).
- Surcharge rates are limited to the four statutory pairs; custom surcharge percentages are not accepted.
- Surcharge pairs are not supported on
TaxPospositions. - There is no field for the customer's regime. Neither TicketBAI nor VERI*FACTU declares the counterparty's tax regime — a customer under REDE is expressed solely through the surcharge amounts.
- A single position cannot carry both a surcharge pair and an additional VAT group.