Taxes and invoices
This guide explains what the store does with taxes, invoices and the right of withdrawal: how it picks the rate, when it stops charging VAT to a business in…
This guide explains what the store does with taxes, invoices and the right of withdrawal: how it picks the rate, when it stops charging VAT to a business in another EU country, how it numbers invoices and how long it gives buyers to change their mind.
What it does not do is decide for you. The store applies what you configure; which rates apply to you and whether you must register for the One-Stop Shop is up to you or whoever handles your taxes.
Taxes are set up in Panel → Taxes; invoices, in Panel → Invoices; and withdrawal, in Panel → Settings → Billing, card "Returns and digital content".
How the rate is chosen
Rates hang from regions: a whole country or a province of that country. Each rate has a name (VAT, IVA, GST, Sales tax…) and a percentage between 0 and 100.
For every cart line and every shipping method, the store looks at the shipping address and keeps one rate, the most specific one that fits. From most to least specific:
- The one for that product (or that shipping method) in the province.
- The one for that product type in the province.
- The province's general rate.
- The one for that product (or shipping method) in the country.
- The one for that product type in the country.
- The country's general rate.
A rate that is also limited to some postcodes or cities beats its equal with no limit. That way a reduced rate for the Canary Islands or for one city overrides the general one without you deleting anything.
Postcodes are separated by ;. They work as they are (08001), with a trailing
wildcard (35*) or as a range (35000...35999). Case, accents and spaces do not
count.
Three more cases:
- Combinable. If the winning province rate is marked as combinable, the country's rate is added. That is the case of a state tax plus a local one.
- Compound. A compound rate is calculated on the price already including the other rates, not on the base. The store keeps the effective percentage so the sums add up.
- Not on shipping. A rate can be left off shipping costs.
If none fits, that line goes without tax. There is no hidden default rate.
Loading the EU standard rates
The panel ships the standard rates of the 27 EU countries, dated January 2026. By default loading them only creates the missing ones: if you already had a country's general rate, it is left alone. You can ask it to replace them.
They are the standard rates. You add reduced ones yourself, per product or per product type.
Import and export
Rates are exported and imported as CSV, with the usual columns from other
stores (country, state, postcode, city, rate, …; Spanish names such as
pais, provincia, cp, tasa also work). If the file has a single error,
nothing is imported: a half-done import leaves mixed rates and nobody knows
which.
An outside service
A plugin can recalculate the rates (the impuestos.calculados filter, see
Write a plugin). If it returns something malformed, fails
or takes more than 5 seconds, the store's own rates stay: checkout does not stop
for somebody else's service. It is not called for an exempt cart.
Prices with or without tax
These are two different settings, and they often get mixed up.
How you store prices. Per currency: either the price you type already includes tax, or tax is added on top. If a region has its own preference, the region's wins.
With tax included, the store takes the base out of the price: €12.10 at 21% is €10.00 base and €2.10 tax. With tax excluded, it adds it: €10.00 at 21% is charged as €12.10.
How they are shown on the storefront. Three options:
| Option | What the customer sees |
|---|---|
con (default) | the price with tax |
sin | the price without tax |
ambos | both |
To work out the other amount before the customer says where they live, the storefront uses the general rate of the store's country. If you have not said which country the store is in and only one country has a general rate, it uses that one; with two or more it does not guess and uses 0.
The default is con because in the EU a consumer is shown the final price.
sin and ambos are for stores that sell to businesses.
Selling to other EU countries
In Panel → Taxes, card "European Union", you state three things: the store's country, your VAT number and whether you are in the One-Stop Shop (OSS). There is a fourth setting, the intra-EU exemption, which comes on and you can switch off.
With that, every cart falls into one of these three cases:
| Case | What tax is charged |
|---|---|
| The customer is in your country, or outside the EU, or the store has no EU country | the normal one: that of the shipping address |
| A business in another EU country with a valid VAT number, and the exemption on | none: reverse charge |
| A consumer in another EU country | with OSS, the customer's country's; without OSS, your country's |
The customer's VAT number and VIES
At checkout the customer can type their VAT number. If it has no country prefix,
the shipping country's is used (Greece uses EL). The store checks it against
VIES, the European Commission's service, on the spot. Your own VAT number goes
in the request as the requester, if you have set it.
Every check is stored: number, whether it was valid, the name and address VIES returned, its request identifier and the date. It is what you can show if someone asks why you did not charge VAT.
If VIES is overloaded, the store retries a couple of times. If it still does not answer, the number does not count as valid and the cart pays the normal tax. When in doubt, the store charges the tax.
When a business is not charged VAT
The exemption only applies if all of this holds:
- the store has an EU country;
- the customer is in another EU country, not the same one as the store;
- the VAT number is valid in VIES and belongs to the same country as the shipping address;
- the intra-EU exemption is switched on.
A business in your own country pays the normal tax even with a valid VAT number. Reverse charge is between different countries.
When it applies, the cart carries the VAT number and the reason: article 138 if there are products that ship, article 196 if there are products with no shipping (services, digital). Both if there are both.
The OSS report
If you are in OSS, the same "European Union" card gives you, between two dates, what was charged to customers in other EU countries: by country, currency and rate, with the taxable base, the tax and the number of orders. It can be downloaded as CSV.
It leaves out cancelled orders, drafts, exempt orders and those charged with your country's tax because OSS was off.
Invoices
Every completed order gets its invoice, and the number is assigned in the same step that creates the order: if the invoice cannot be numbered, the order is not created.
Chained numbering
Invoices go in series, and within each series the numbers are consecutive: 1, 2, 3… with no gaps.
| Series | What it holds |
|---|---|
A | order invoices (changed with SERIE_FACTURA) |
M | manual invoices |
R | corrective invoices (credit notes) |
Every invoice stores a hash: a SHA-256 digest of its issuer tax ID, its series and number, its date, its tax, its total and the hash of the previous invoice. That is why they are chained. If someone changes an old invoice in the database, or deletes one, the chain stops adding up from there, and the store can tell in which number it breaks.
Two orders closing at the same time do not get the same number: the store locks the series' last invoice while it assigns the next one.
Every issued invoice fires the factura.emitida event. That is how an
e-invoicing connector picks up the invoice and leaves its stamp.
Manual invoices
To bill something that does not go through the store (a commission, a service), in Panel → Invoices you create an invoice by hand: customer, lines with quantity, price and rate, notes and due date.
It starts as a draft. A draft can be edited and deleted as much as you
like, and has no number. When you issue it, it gets the next number in
series M, joins the chain and can no longer be changed or deleted.
You can mark an invoice as paid or unpaid at any time: that does not touch the chain.
Corrective invoices
An issued invoice is not edited: it is corrected with a corrective invoice. You can make one from a manual invoice or from an order, and it asks for a reason.
- From a manual invoice, it copies its lines with negative quantities.
- From an order, it copies its lines and shipping with the exact amounts that were invoiced, negative. It does not recalculate them: a corrective invoice has to cancel what was charged, not what it would come to today.
The corrective invoice starts as a draft, so you can remove the lines that do
not apply (a partial return). When issued it gets a number in series R and
records which invoice it corrects.
Right of withdrawal
Withdrawal is the buyer's right to back out of a distance purchase. How many days they have, and whether the store gives them a button to ask for it, depends on the legal profile of the order's country.
Which profile applies
For each order's button, the store looks at the country of the shipping address (and, if there is none, the billing one). For the summary you see in the panel, it looks at the country you pick there or, if you pick none, the one in the store's tax details.
| Profile | Period | Days | Button in the store |
|---|---|---|---|
| EU (the 27 plus Norway, Iceland and Liechtenstein) | 14 | calendar | yes |
| United Kingdom | 14 | calendar | no |
| Turkey | 14 | calendar | no |
| Brazil | 7 | calendar | no |
| Mexico | 5 | business | no |
| United States, Canada, Australia, India, everywhere else | no legal period | — | no |
Where there is no button, a customer who wants to return something writes to you. Where there is no legal period, your returns policy rules.
The button
In the European profile, the order page shows how many days are left and lets the customer choose which items go back. When they ask:
- The request is stored with the date, the items and the reason, if given.
- The customer gets an email on the spot, in their language, confirming you received it.
- It goes into the order's audit history.
- It shows up in the
/gestion/desistimientoslist, where you mark it as handled with a note (POST /gestion/desistimientos/:id/atender).
How the period is counted:
- From receipt, if the country profile says so and there is something physical in the order; with several deliveries, from the last one. Until everything has been delivered, the period has not started and the buyer can withdraw: that is why it pays to mark deliveries. A digital-only order counts from the order.
- In calendar or business days, depending on the profile (Mexico: 5 business days).
- The day of delivery does not count, the period ends at the end of its last day and, if that day is a Saturday or Sunday, it moves to the Monday. Public holidays are not taken into account: the system does not have each region's calendar.
Once it has passed, the button no longer accepts the request.
What is left out
Some items cannot be withdrawn from. The store separates them by itself and the email to the customer says which ones and why:
- Made to order: items carrying a customisation with the customer's data. In the EU, the United Kingdom and Turkey they are excluded by default; in Brazil and Mexico, only if you switch it on. Where there is no legal period, it does not apply.
- Digital content already downloaded: as soon as the customer starts downloading it, that line leaves the withdrawal.
If everything they choose is left out, no request is created and they are told why.
Digital content
In the EU, United Kingdom and Turkey profiles, checkout asks the customer to agree to receive the digital content now and to lose withdrawal for that part once the download starts. The text, and whether it is required, are changed on the same panel card.
See also
- Write a plugin: the tax filter and the invoice event.
- API routes: the
/gestion/impuestos,/gestion/facturas-manuales,/gestion/legaland/gestion/desistimientosroutes.