EU OSS destination VAT
Space Invoices provides an EU OSS sales report and two ways to apply destination VAT:
- A sales report groups finalized intra-EU B2C invoices and credit notes by destination country and compares eligible EUR sales with the EU-wide €10,000 threshold.
- A saved destination tax lets you choose an explicit foreign rate for a document line. Use it for reduced rates, services, or whenever you do not want automatic standard-goods switching.
- An optional automatic rule replaces a recognizable standard VAT rate with the destination country’s standard rate on eligible product lines.
The report does not enable either tax workflow, and the automatic rule does not wait for the report to cross the threshold. Decide when destination VAT applies with your tax adviser, then use saved taxes or enable the automatic rule for new calculations.
Prerequisites
| Requirement | Description |
|---|---|
| Eligible issuer | The entity is in the EU and is a VAT subject. |
| Destination customer | The effective customer is in another EU country and the transaction is classified as intra_eu_b2c. |
| Saved destination tax | Choose an EU destination country other than the issuer country. The customer’s country must match it when the tax is used. |
| Automatic goods classification | Set items[].classification to product, or use a catalog item_id whose saved classification is product. Services and unclassified lines are not switched automatically. |
| Automatic standard VAT | Use a tax classified as standard, a saved standard tax through tax_id, or the issuer country’s standard rate. The tax classification itself is optional. |
The OSS report, automatic rule, and saved-tax destination field are not offered for entities in Hungary, Poland or Portugal. Their mandatory e-invoicing or fiscalization submission paths cannot accept these foreign VAT rates.
For a customer with a VAT number, VIES can change the transaction to intra_eu_b2b. A valid number remains B2B. A rejected number is treated as B2C. If VIES is unavailable, a customer with a VAT number remains B2B, so destination VAT is not applied automatically.
1. Review sales by country
Call the report for the year you are reviewing. It returns that year and the preceding calendar year:
curl "https://eu.spaceinvoices.com/tax-reports/eu/oss?year=2026" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "x-entity-id: YOUR_ENTITY_ID"Use the response as follows:
| Field | Meaning |
|---|---|
periods[].countries[] | Per-country invoice count, credit-note count, net sales, collected VAT and gross sales. |
periods[].net_sales | The EU-wide net total for that calendar year. It is not a separate €10,000 allowance for each country. |
threshold.status | below_threshold, exceeds_threshold, or comparison_unavailable. Either the selected or preceding year’s net sales can make the status exceed the threshold. |
auto_apply_destination_vat | Whether the entity’s optional automatic switch is currently enabled. |
vat_rates_verified_through | ISO date through which the bundled standard-rate table was last verified. |
notices | Stable scope and data-quality reminder codes. vat_rates_last_verified tells clients to display vat_rates_verified_through. |
Only finalized, non-voided, non-deleted intra-EU B2C invoices and credit notes are included. Credit notes reduce the totals. A threshold comparison is available only for an EUR entity when every included line is a product and all required stored currency conversions are complete. Country totals can still help with review when the threshold comparison is unavailable.
2. Create a saved destination tax
For an eligible entity, create or edit a saved tax, open Advanced, and choose its Destination VAT country. Then select that saved tax on the document line. The rate can be standard or reduced, and the line can represent goods or services. You do not need to enable the automatic rule.
The destination must be an EU country other than the issuer country. The API applies the same rule when you create or replace a tax. For example, create a saved German reduced rate:
curl -X POST "https://eu.spaceinvoices.com/taxes" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "x-entity-id: YOUR_ENTITY_ID" \ -H "Content-Type: application/json" \ -d '{ "name": "German reduced VAT", "destination_vat_country_code": "DE", "tax_rates": [{ "rate": 7 }] }'The response includes the saved tax ID and normalized destination:
{ "id": "tax_6595a27b5d35015c3ef0c3ff", "destination_vat_country_code": "DE"}Use the returned id as the line’s tax_id. This example applies the saved rate to a service for a German consumer:
curl -X POST "https://eu.spaceinvoices.com/invoices" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "x-entity-id: YOUR_ENTITY_ID" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cus_german_consumer", "items": [ { "name": "Online service", "classification": "service", "quantity": 1, "price": 100, "taxes": [{ "tax_id": "tax_6595a27b5d35015c3ef0c3ff" }] } ] }'The document must classify as intra_eu_b2c, and the customer’s country must match the saved tax’s destination. Otherwise document creation, update, and calculation-preview requests fail with 422. The server copies the saved country marker onto the resolved line tax. The line’s classification remains authoritative for goods-versus-services reporting; the marker does not mean that the rate is standard or that the line is a product.
See create a saved tax, replace a saved tax, and create an invoice for complete request and response schemas.
3. Enable the automatic switch
Update the entity with settings.tax_rules.eu.auto_apply_destination_vat: true:
curl -X PUT "https://eu.spaceinvoices.com/entities/YOUR_ENTITY_ID" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "x-account-id: YOUR_ACCOUNT_ID" \ -H "Content-Type: application/json" \ -d '{ "settings": { "tax_rules": { "eu": { "auto_apply_destination_vat": true } } } }'The server merges tax_rules by region and merges the EU block by field. EU fields and country branches omitted from the request remain unchanged; an explicit null still clears a nullable field.
Enabling the setting does not rewrite existing documents in bulk. It applies when a standard document is created or previewed. Drafts are re-evaluated when their customer, customer_id, items or date changes. A customer_id-only retarget resolves and stores the selected customer’s snapshot, runs transaction classification and VIES once, and rerates automatically applied destination VAT where applicable. Issued documents keep their stored taxes, totals and destination marker state, including the absence of a marker. A credit note created from an invoice keeps the source invoice’s line taxes and destination-country marker instead of applying the current destination rate again. The standard invoice, estimate, credit-note, advance-invoice and delivery-note flows use the same rule. Custom pre-calculated document endpoints do not change taxes.
An explicitly marked saved tax is left unchanged by the automatic rule. Its saved rate and destination remain authoritative even when automatic switching is enabled.
A draft customer_id-only update uses the selected saved customer as the new frozen snapshot. If the new context no longer qualifies for destination VAT, an automatically applied destination rate is removed or replaced as appropriate. An explicitly selected marked saved tax remains authoritative and a country or transaction-type mismatch fails with 422 instead of being silently rewritten.
Shopify, WooCommerce and Magento
Imported store orders can obtain the required product classification after you enable Treat imported items as products in the integration settings:
- When a regular order line’s SKU matches a Space Invoices catalog item, the document line inherits that catalog item’s classification. The store’s name, quantity, price and taxes remain authoritative.
- An otherwise-unclassified regular order line is classified as a product. Shipping and fee lines are never changed by this setting.
Newly connected stores are active and process orders automatically by default. Treat imported items as products is a separate classification fallback: it remains off for existing and newly connected stores until you enable it. This prevents mixed or digital catalogs from being classified as goods accidentally. A catalog classification matched by SKU takes precedence over the store default.
API clients can enable the same setting on an existing Shopify, WooCommerce, Magento or custom-store integration:
curl -X PATCH "https://eu.spaceinvoices.com/order-integrations/YOUR_INTEGRATION_ID" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "x-entity-id: YOUR_ENTITY_ID" \ -H "Content-Type: application/json" \ -d '{ "classify_imported_items_as_products": true }'Set the field to false or null to disable imported-item classification. With it off, SKU linking still attaches the catalog item_id, but does not copy the catalog classification onto the imported document line. Disabling it does not remove classifications already stored on issued documents or catalog items created while it was enabled.
4. Send an eligible product line
This preview is for a Slovenian entity selling goods to a German consumer. The supplied 22% Slovenian standard rate is replaced with Germany’s 19% standard rate before totals are calculated:
curl -X POST "https://eu.spaceinvoices.com/documents/calculate?type=invoice" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "x-entity-id: YOUR_ENTITY_ID" \ -H "Content-Type: application/json" \ -d '{ "customer_id": "cus_german_consumer", "date": "2026-10-05", "items": [ { "name": "Product", "classification": "product", "quantity": 1, "price": 100, "taxes": [{ "classification": "standard" }] } ] }'The item and tax classifications serve different purposes. The item must be known to be a product; on normal create and preview calls, a catalog item_id supplies its saved classification. The tax does not need an explicit classification if Space Invoices can recognize it another way.
You can identify the standard tax in any one of these ways:
- Send
classification: "standard"on the tax. - Send
tax_idfor an entity tax whose classification isstandard. - Send a raw
rateequal to the issuer country’s date-effective standard rate.
Tags and financial categories are not used to decide whether a line is eligible. Arbitrary assigned rates are not assumed to be standard.
Net and gross prices
The destination rate is selected before document totals are calculated. Which amount stays fixed depends on the price field you send:
| Input for one item | Before the switch at 22% | After the switch to 19% |
|---|---|---|
price: 100 | Net €100, VAT €22, gross €122 | Net stays €100, VAT becomes €19, gross becomes €119 |
gross_price: 122 | Gross €122, net €100, VAT €22 | Gross stays €122, net becomes €102.52, VAT becomes €19.48 |
Use price when your catalog price is tax-exclusive and the customer total should change with the destination rate. Use gross_price when the advertised customer price is tax-inclusive and should stay fixed; the API recalculates the net amount and VAT share.
Send either price or gross_price on a line, not both. Discounts follow the document’s normal calculation mode after the destination rate is selected.
When the server applies automatic destination VAT or resolves a marked saved tax, the returned and stored line tax includes a read-only destination_vat_country_code such as DE or IT. This marker identifies the foreign VAT for OSS and Slovenian accounting exports. At line level it is server-owned: send the saved tax_id, not a country marker. Previews and draft updates derive it again, while issued documents retain the stored value.
A typed inline rate and an unmarked saved tax remain unmarked and keep the existing validation and export behavior. To mark a manually selected foreign rate for OSS, set the destination on the saved tax and reference its tax_id.
Slovenian accounting exports
For a Slovenian issuer, KIR, VOD and miniMAX use the destination marker to recognize a destination-VAT line, whether produced automatically or selected from saved taxes:
- KIR puts the line’s taxable base in
P27. Its foreign VAT is not reported inP14,P15orP16, and the base is not reported inP7. Foreign-currency documents use their stored EUR conversions. - VOD emits separate
Osnova_splosna_stopnja_blagoorOsnova_splosna_stopnja_storitevandDDV_splosna_stopnja_*entries withDrzava_potrosnje. The foreign VAT is kept out of the Slovenian VAT buckets, and stored converted amounts are used for non-EUR documents. - miniMAX emits the normal receivable and revenue entries plus the foreign-VAT liability row. That row carries
PredlozitevObracunaOSS=D,Drzava,Odstotek,BlagoStoritev,DatumDDVand both base amounts, allowing miniMAX to prepare its OSS calculation.BlagoStoritevfollows the document line’s goods-or-services classification, not the destination marker.
The EU OSS report independently selects finalized, non-voided intra_eu_b2c invoices and credit notes, then groups totals by transaction type and customer country. It does not select lines by the destination marker. The foreign VAT itself belongs in the separate quarterly OSS return; the report supplies per-country operational totals.
What is left unchanged
The automatic rule does not add a tax to an untaxed line. It also leaves these lines unchanged unless you explicitly select a marked saved tax:
serviceor unclassified items- reduced, zero, exempt, reverse-charge and arbitrary custom rates
- custom pre-calculated documents
An explicitly marked saved tax is also left unchanged by the automatic rule. A typed inline rate or an unmarked saved tax does not become marked merely because its numeric rate matches a foreign VAT rate.
Draft customer retargets resolve the replacement snapshot, run classification and VIES once, and persist the resulting transaction type. Eligible automatically applied destination VAT is rerated to the new destination or restored to issuer VAT when the draft becomes domestic. Issued documents keep their stored transaction type, taxes and marker state. Changing only the entity setting does not retroactively recalculate stored documents.
The bundled standard-rate table remains in use after its displayed verification date instead of silently disabling automation. Settings and the report show the date so you can review whether a newer reference is required.
Related API
See EU OSS sales tracking, update an entity, update an order integration, preview a document calculation, and create an invoice.