<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[W System]]></title><description><![CDATA[W System]]></description><link>https://wsystem.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 31 Oct 2026 23:14:52 GMT</lastBuildDate><atom:link href="https://wsystem.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Spain B2B e-invoicing from 6 October 2027: what invoicing software must ship]]></title><description><![CDATA[Spain's B2B e-invoicing dates are fixed: 6 Oct 2027 above EUR 8m, 2028 for all. Formats, UBL copy to AEAT, checklist.]]></description><link>https://wsystem.hashnode.dev/spain-b2b-e-invoicing-2027-software</link><guid isPermaLink="true">https://wsystem.hashnode.dev/spain-b2b-e-invoicing-2027-software</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[eInvoicing]]></category><category><![CDATA[api]]></category><category><![CDATA[Spain]]></category><category><![CDATA[SaaS]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 22 Oct 2026 10:57:13 GMT</pubDate><content:encoded><![CDATA[<p>If you build invoicing, ERP or accounting software with Spanish customers, the waiting is over: Order HAC/1028/2026 entered into force on <strong>6 October 2026</strong>, which fixes the B2B e-invoicing dates in Royal Decree 238/2026. Businesses with more than <strong>EUR 8 million</strong> volume of operations start on <strong>6 October 2027</strong>, everyone else on <strong>6 October 2028</strong>. Here is what that means for your product.</p>
<h2>The dates</h2>
<table>
<thead>
<tr>
<th>Date</th>
<th>What changes</th>
</tr>
</thead>
<tbody><tr>
<td>6 Oct 2026</td>
<td>Order HAC/1028/2026 in force; the 12- and 24-month clocks start.</td>
</tr>
<tr>
<td>By early Aug 2027</td>
<td>The AEAT's public e-invoicing solution must be available (at least two months before it first applies).</td>
</tr>
<tr>
<td>6 Oct 2027</td>
<td>Issuers above EUR 8 million must issue and receive B2B e-invoices. Private platforms must send faithful copies to the AEAT and interconnect.</td>
</tr>
<tr>
<td>6 Oct 2027 – 5 Oct 2028</td>
<td>Those large issuers also send a readable PDF with each e-invoice, unless the buyer accepts the XML alone.</td>
</tr>
<tr>
<td>6 Oct 2028</td>
<td>Everyone else, including the self-employed.</td>
</tr>
<tr>
<td>6 Oct 2029</td>
<td>Status reporting becomes mandatory for individuals and income-attribution entities up to EUR 8 million.</td>
</tr>
</tbody></table>
<p>Scope: invoices to businesses and professionals established in Spain. Simplified invoices are out unless they are qualified simplified invoices.</p>
<h2>Formats</h2>
<ul>
<li>EN 16931 in <strong>UBL, CII, EDIFACT or Facturae</strong>. Peppol BIS is accepted on private platforms.</li>
<li>The AEAT's public solution uses <strong>UBL only</strong>, with Spanish fields (copy indicator, payment date, withholdings, VERI*FACTU / TicketBAI QR reference) and no embedded files.</li>
<li>Invoices through private platforms need an <strong>advanced electronic signature</strong>.</li>
<li>Each invoice has a unique code: issuer NIF + series and number + issue date.</li>
</ul>
<h2>The faithful copy</h2>
<p>If an invoice does not go through the public solution, the system that issues it must send the AEAT a <strong>faithful copy in UBL at the moment of issue</strong>, flagged with <code>cbc:CopyIndicator = true</code>. The AEAT validates it; a rejected copy must be fixed and resent, and duplicates are rejected.</p>
<h2>Status and payment reporting</h2>
<p>Buyers report acceptance or rejection and full payment (with dates) to the issuer, and full payment or rejection plus the due date to the AEAT, within four days excluding weekends and national holidays. No rejection means the invoice is presumed accepted.</p>
<h2>VERI*FACTU</h2>
<p>Separate regime. Legal dates are 1 January 2027 (corporate taxpayers) and 1 July 2027 (others); on 5 October 2026 the Ministry of Finance announced a move to October 2028, which still needs a new legal text.</p>
<h2>Checklist for builders</h2>
<ul>
<li>Segment users by the EUR 8 million threshold.</li>
<li>Emit EN 16931 UBL (it is what the AEAT and the copy use).</li>
<li>Decide: integrate the AEAT public solution yourself or connect a private platform.</li>
<li>Add Spanish fields: copy indicator, IRPF withholdings, corrective-invoice codes, VERI*FACTU / TicketBAI reference.</li>
<li>Enforce unique invoice numbers per series before anything reaches the AEAT.</li>
<li>PDF companion for large issuers in year one.</li>
<li>Record and report acceptance, rejection and payment within four working days.</li>
<li>Validate against EN 16931 before sending.</li>
</ul>
<h2>Try it with an API</h2>
<p><em>Disclosure: I build W System, the API used here.</em> <code>POST https://api.wsystem.dev/einvoice/create</code> with <code>"format": "peppol-bis3"</code> and Spanish parties returns an EN 16931 UBL invoice checked against EN 16931. It does not add the Spanish BT-ES fields, sign, or send anything to the AEAT; use it to test your EN 16931 output, or drop a file into the free validator at wsystem.dev/e-invoice-validator. Full article with sources (BOE texts) and the live response: <a href="https://wsystem.dev/spain-b2b-e-invoicing-2027-software">https://wsystem.dev/spain-b2b-e-invoicing-2027-software</a></p>
<p>Not tax advice.</p>
]]></content:encoded></item><item><title><![CDATA[Norway e-invoicing from 1 January 2027: what invoicing software must ship]]></title><description><![CDATA[Norway's B2B e-invoice duty from 2027 for software builders: EHF / Peppol BIS 3.0, exemptions, 0192 addressing, checklist.]]></description><link>https://wsystem.hashnode.dev/norway-e-invoicing-2027-software</link><guid isPermaLink="true">https://wsystem.hashnode.dev/norway-e-invoicing-2027-software</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[norway]]></category><category><![CDATA[peppol]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[api]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 22 Oct 2026 10:57:03 GMT</pubDate><content:encoded><![CDATA[<p>If you build invoicing, ERP or accounting software with Norwegian customers, this post sums up what the new Norwegian rules mean for your product: from <strong>1 January 2027</strong> businesses must invoice each other with structured e-invoices, the buyer's organisation number becomes mandatory in 2028, and everyone must be able to receive in 2030.</p>
<h2>The rules in one table</h2>
<table>
<thead>
<tr>
<th>Date</th>
<th>What changes</th>
</tr>
</thead>
<tbody><tr>
<td>1 Jan 2027</td>
<td>Bookkeeping-obligated businesses issue sales documents to other bookkeeping-obligated businesses as <strong>e-invoices</strong> (Bookkeeping Act § 10). Approved formats: EHF Billing, Peppol BIS Billing, EHF Self-Billing, Peppol BIS Self-Billing, version 3.0+ (Regulation § 5-2-9).</td>
</tr>
<tr>
<td>1 Jan 2027 – 31 Dec 2029</td>
<td>The parties may agree another structured format (e.g. EDIFACT, E2B). PDF never counts when the buyer can receive.</td>
</tr>
<tr>
<td>1 Jan 2028</td>
<td>The buyer's organisation number (plus MVA if VAT-registered) must be on every B2B sales document, and the document must always be sent to the buyer.</td>
</tr>
<tr>
<td>1 Jan 2030</td>
<td>Duty to <strong>receive</strong> e-invoices, and bookkeeping in an electronic accounting system.</td>
</tr>
</tbody></table>
<p>Until 2030 the issue duty applies in practice only when the buyer can receive, typically because it is registered in ELMA / Peppol (Skatteetaten, 29 September 2026).</p>
<h2>Exemptions</h2>
<ul>
<li>Turnover up to NOK 50,000 a year, for businesses that only file an income tax return: no duty to receive, and issue only if their invoicing system can. Not for accounting-obligated businesses or VAT filers.</li>
<li>Bankruptcy estates, and specific rules for finance, insurance and pension companies.</li>
<li>Sales to consumers are outside the B2B duty.</li>
</ul>
<h2>Peppol addressing</h2>
<p>Norwegian companies are addressed as <strong>0192</strong> + the bare nine-digit organisation number (e.g. <code>0192:923609016</code>). The VAT number on the invoice is <code>NO923609016MVA</code>, but the endpoint is the organisation number. AS, ASA and NUF sellers should also show "Foretaksregisteret" (Peppol rule NO-R-002).</p>
<h2>Checklist for builders</h2>
<ul>
<li>Emit EHF / Peppol BIS Billing 3.0, or connect an access point that does.</li>
<li>Look up Norwegian business customers on Peppol before sending a PDF.</li>
<li>Store every customer's organisation number now (mandatory on invoices from 2028, and it is the Peppol address).</li>
<li>Keep the e-invoice XML in its original format.</li>
<li>Plan inbound e-invoices for 2030.</li>
<li>Track any EDIFACT / other-format agreements; they must end by 31 December 2029.</li>
</ul>
<h2>Try it with an API</h2>
<p><em>Disclosure: I build W System, the API used here.</em> <code>POST https://api.wsystem.dev/einvoice/create</code> with <code>"format": "peppol-bis3"</code> and Norwegian parties returns a Peppol BIS 3 UBL invoice with <code>0192</code> endpoints derived from the organisation numbers, checked against EN 16931 (Peppol-specific rules are not run yet, and nothing is sent). <code>GET /einvoice/route?id=NO923609016MVA</code> checks the public Peppol Directory and returns the Norwegian rules. Free for 20 calls a day; the full article with a live example and sources (Lovdata, regjeringen.no, Skatteetaten) is at <a href="https://wsystem.dev/norway-e-invoicing-2027-software">https://wsystem.dev/norway-e-invoicing-2027-software</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Poland KSeF from 1 January 2027: what invoicing software must change (fines now planned for 2028)]]></title><description><![CDATA[KSeF is mandatory for every Polish business from 1 Jan 2027; fines move to 2028 (bill adopted 20 Oct). Checklist for software.]]></description><link>https://wsystem.hashnode.dev/poland-ksef-2027-invoicing-software</link><guid isPermaLink="true">https://wsystem.hashnode.dev/poland-ksef-2027-invoicing-software</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[poland]]></category><category><![CDATA[ksef]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[api]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 22 Oct 2026 09:02:57 GMT</pubDate><content:encoded><![CDATA[<p>If you build invoicing, POS or payment software with Polish customers, this post gives you what changes on 1 January 2027 when KSeF becomes mandatory for every business, what the government decided on 20 October 2026 about fines, and a checklist, all from official KSeF sources.</p>
<h2>What changed on 20 October 2026</h2>
<p>The Council of Ministers adopted the draft VAT amendment known as UD477. It moves fines for not using KSeF (or using it wrongly) from <strong>1 January 2027</strong> to <strong>1 January 2028</strong>. KSeF itself stays mandatory: in 2027 the tax administration will first remind a business individually and then check its VAT if it doesn't react. The bill still has to pass the Sejm and the Senate and be signed; it is meant to enter into force on 31 December 2026. Until it is published, plan as if the current dates apply.</p>
<h2>Timeline</h2>
<table>
<thead>
<tr>
<th>Date</th>
<th>What applies</th>
</tr>
</thead>
<tbody><tr>
<td>1 Feb 2026</td>
<td>KSeF mandatory for issuing for businesses with 2024 sales above PLN 200 million (incl. VAT); every business must receive in KSeF</td>
</tr>
<tr>
<td>1 Apr 2026</td>
<td>KSeF mandatory for issuing for all other businesses, including VAT-exempt ones</td>
</tr>
<tr>
<td>Until 31 Dec 2026</td>
<td>Up to PLN 10,000 a month of invoiced sales may still be invoiced outside KSeF; cash-register invoices and receipts with the buyer's NIP (up to PLN 450) stay outside KSeF</td>
</tr>
<tr>
<td>1 Jan 2027</td>
<td>KSeF for everyone; cash-register invoices end; transfers between active VAT payers must quote the KSeF number (art. 108g)</td>
</tr>
<tr>
<td>1 Jan 2028</td>
<td>Fines start, if bill UD477 passes (today's law: 1 Jan 2027)</td>
</tr>
</tbody></table>
<h2>What a KSeF invoice is</h2>
<ul>
<li>The <strong>FA(3)</strong> structure, a Polish XML schema. It is not UBL, CII or Peppol BIS.</li>
<li>It counts as issued on the day it is sent to KSeF. KSeF returns a <strong>KSeF number</strong> in the official receipt (UPO); it is not in the XML and differs from your own invoice number (field P_2).</li>
<li>Delivered through KSeF to Polish business buyers. Foreign buyers without a Polish establishment and consumers get it in an agreed way (for example a PDF) with a QR code and the KSeF number.</li>
</ul>
<h2>Checklist before 1 January 2027</h2>
<ul>
<li><strong>Drop the PLN 10,000 logic.</strong> Every B2B invoice now goes through KSeF.</li>
<li><strong>POS and shop systems:</strong> cash-register invoices and receipts with a NIP stop counting as invoices. Issue business invoices for register sales in KSeF.</li>
<li><strong>Store the KSeF number</strong> per invoice from the UPO and pass it to accounting and payments.</li>
<li><strong>Payment files:</strong> put the KSeF number (or a KSeF collective identifier for several invoices) in the transfer title, also in split-payment (MPP) messages, when both sides are active VAT payers; the payee's status comes from the official VAT white list on the payment day.</li>
<li><strong>Offline modes:</strong> offline24 lets you issue outside KSeF and send by the next business day; an offline invoice handed over outside KSeF needs two QR codes (OFFLINE and CERTYFIKAT), and the second needs a KSeF certificate obtained in advance.</li>
<li><strong>Foreign buyers:</strong> still issue in KSeF, then send a PDF with the KSeF QR code and number.</li>
<li><strong>Receiving:</strong> every Polish business has had to receive in KSeF since 1 February 2026.</li>
</ul>
<h2>Fines once they apply</h2>
<p>Art. 106ni of the VAT Act: up to <strong>100% of the VAT</strong> on an invoice issued outside KSeF against the rules, or up to <strong>18.7% of the total</strong> when the invoice shows no VAT. Not tax advice.</p>
<h2>Routing check in a multi-country app</h2>
<p><em>Disclosure: I work on W System, which makes this API.</em> W System does not submit to KSeF and does not create or validate FA(3). In a multi-country invoicing app, <code>GET https://api.wsystem.dev/einvoice/route?id=PL7740001454</code> checks the buyer's VAT number in VIES, looks it up in the Peppol Directory and returns the country's mandate, so your app knows a Polish buyer needs KSeF FA(3) while a Belgian one needs Peppol BIS 3. Free for 20 calls a day per IP.</p>
<p>The full version with sources, FAQ and the live response is at <a href="https://wsystem.dev/poland-ksef-2027-invoicing-software">https://wsystem.dev/poland-ksef-2027-invoicing-software</a>.</p>
]]></content:encoded></item><item><title><![CDATA[France e-invoicing: what invoicing software must fix before SMEs start issuing on 1 September 2027]]></title><description><![CDATA[France's reform is live: 75% chose a platform, 20M+ invoices in a month. SMEs issue from 1 Sep 2027. Mentions, rejections, checklist.]]></description><link>https://wsystem.hashnode.dev/france-e-invoicing-2027-sme-software</link><guid isPermaLink="true">https://wsystem.hashnode.dev/france-e-invoicing-2027-sme-software</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[FRAnce]]></category><category><![CDATA[Factur X]]></category><category><![CDATA[SaaS]]></category><category><![CDATA[api]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Tue, 20 Oct 2026 04:01:20 GMT</pubDate><content:encoded><![CDATA[<p>If you build invoicing or ERP software with French customers, this post gives you where the French reform stands after its first month, what changes on 1 September 2027 when SMEs and micro-enterprises must start issuing e-invoices, the four new mandatory mentions, how the official guide says to handle rejected and refused invoices, the penalties, and a checklist.</p>
<h2>Where France stands</h2>
<p>The reform went live on <strong>1 September 2026</strong>: every VAT-registered business in France must be able to receive e-invoices through an approved platform (plateforme agréée), and large companies and mid-caps (ETI) must issue them and send e-reporting data.</p>
<p>At the first follow-up committee on 8 October 2026 the government gave these figures as of 4 October: <strong>75%</strong> of businesses filing VAT had chosen a receiving platform, and more than <strong>20 million</strong> invoices worth over <strong>EUR 70 billion</strong> had been exchanged. Business organisations raised the cost and readability of platform offers, switching platforms, adapting software and the needs of the smallest firms. Large companies pointed to interoperability problems between some solutions and to lifecycle statuses not being passed on correctly. The minister confirmed that <strong>no business will be fined before the end of 2026</strong>, and the starting guide is being updated.</p>
<h2>Timeline</h2>
<table>
<thead>
<tr>
<th>Date</th>
<th>What happens</th>
</tr>
</thead>
<tbody><tr>
<td>1 Sep 2026</td>
<td>All businesses receive via an approved platform; large companies and ETI issue and e-report</td>
</tr>
<tr>
<td>Until 31 Dec 2026</td>
<td>No fines (the obligation itself is not postponed)</td>
</tr>
<tr>
<td>1 Sep 2027</td>
<td>SMEs, very small businesses and micro-enterprises issue; e-reporting ramps up; line description, quantity and unit price join the transmitted data</td>
</tr>
</tbody></table>
<h2>What a French e-invoice has to be</h2>
<ul>
<li>A structured format: <strong>UBL, CII, or Factur-X</strong> (structured data plus a readable image). The common minimum every platform supports is AFNOR <strong>XP Z12-012</strong>; platform APIs are XP Z12-013, B2B use cases XP Z12-014.</li>
<li>Sent through an approved platform. A PDF by e-mail is not an e-invoice under the reform.</li>
<li><strong>Four new mentions:</strong> the client's SIREN (when the client is a business), the delivery address if different, the nature of the operations (goods, services or both), and "Option pour le paiement de la taxe d'après les débits" when the supplier opted to pay VAT on debits.</li>
</ul>
<h2>Rejected is not refused</h2>
<p>The official starting guide separates the cases your software has to handle:</p>
<ul>
<li><strong>Rejected by a platform:</strong> format error, missing or inconsistent mandatory data, wrong party, routing problem. Fix the file and send it again electronically; keep the file, the message, the cause and the correction.</li>
<li><strong>Refused by the buyer:</strong> a lifecycle status that must give a reason and may only be used for the reasons the standard allows, not for a commercial dispute. If you re-issue, use a <strong>new invoice number</strong>.</li>
<li><strong>Recipient not found in the directory:</strong> check SIREN, SIRET, establishment and name, then ask your platform, then the client. An e-mailed copy is a continuity measure, not a new invoice.</li>
<li><strong>Duplicates:</strong> re-sending must never cause double payment, booking or VAT deduction; mark copies and link them to the original.</li>
</ul>
<h2>Penalties (2026 finance law)</h2>
<ul>
<li>EUR 50 per invoice not issued electronically, at most EUR 15,000 a year.</li>
<li>EUR 500 per missing e-reporting transmission, at most EUR 15,000 a year per type.</li>
<li>No receiving platform: formal notice, then EUR 500 after three months and EUR 1,000 for each further three months.</li>
<li>A first offence fixed spontaneously or within 30 days of a request is not fined.</li>
</ul>
<h2>Checklist before 1 September 2027</h2>
<ol>
<li>Connect to at least one approved platform's API for issuing and receiving; let customers switch platform without re-keying.</li>
<li>Store the client's SIREN (and SIRET where used) and put supplier and client SIREN in the invoice's legal registration identifiers (BT-30 / BT-47, scheme 0002); check the field against your platform's XP Z12-012 profile.</li>
<li>Add the four new mentions, including a separate delivery address and a goods/services/both flag.</li>
<li>Make line description, quantity and unit price mandatory.</li>
<li>Validate against EN 16931 before sending, then your platform's XP Z12-012 rules; show the rule and the field, not just "rejected".</li>
<li>Store and show lifecycle statuses; re-send after a rejection, new number after a refusal.</li>
<li>Prevent duplicates and keep the evidence the guide asks for.</li>
</ol>
<h2>Catching a missing client SIREN before the platform does</h2>
<p>Disclosure: I build W System, an EU e-invoicing and counterparty-check API. It is not an approved French platform and does not transmit invoices in France. What it does help with here: validating your UBL, CII and Factur-X files against EN 16931, and, for French parties, flagging a missing supplier or client SIREN (with a suggested value from the FR VAT number) before you hand the file to your platform. You can try it in the free in-browser validator at wsystem.dev/e-invoice-validator. The full article, with a live API response and all official sources, is on wsystem.dev.</p>
<p>Not tax advice; re-check the official guide before you release.</p>
]]></content:encoded></item><item><title><![CDATA[Greece e-invoicing from 2 November 2026: what invoicing software needs to ship]]></title><description><![CDATA[Greek B2B e-invoicing wave 2 starts 2 Nov 2026; ERP only in parallel until 31 Jan 2027. Timeline, provider vs ERP, MARK/QR, checklist.]]></description><link>https://wsystem.hashnode.dev/greece-e-invoicing-2-november-2026</link><guid isPermaLink="true">https://wsystem.hashnode.dev/greece-e-invoicing-2-november-2026</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[greece]]></category><category><![CDATA[mydata]]></category><category><![CDATA[ERP]]></category><category><![CDATA[api]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Mon, 19 Oct 2026 15:58:49 GMT</pubDate><content:encoded><![CDATA[<p>If you build invoicing or ERP software with Greek customers, this post gives you the dates that matter for the second wave of Greek B2B e-invoicing, what is in scope, why "our ERP talks to myDATA" stops being enough on 1 February 2027, and a checklist to work through before 2 November 2026.</p>
<h2>The short version</h2>
<p>From <strong>2 November 2026</strong> the remaining Greek businesses (2023 gross revenue up to EUR 1 million) must issue electronic invoices for domestic B2B wholesale, B2B wholesale to non-EU countries and B2G (joint decision A.1128/2025 as amended by A.1197/2026, published 30 September 2026). Businesses above EUR 1 million have been in since 2 March 2026. Until <strong>31 January 2027</strong> a declared ERP or special-form path can still run in parallel; from <strong>1 February 2027</strong> only an AADE-licensed provider or AADE's free timologio / myDATAapp may issue in-scope invoices.</p>
<h2>Timeline</h2>
<ul>
<li><strong>2 Mar 2026:</strong> first period (gross revenue over EUR 1m) mandatory; recipients must accept domestic B2B and B2G e-invoices.</li>
<li><strong>30 Sep 2026:</strong> A.1197/2026 moves the second-period start from 1 October to 2 November 2026.</li>
<li><strong>2 Nov 2026:</strong> second period starts. The start declaration (provider or timologio) must give a start date no later than 2 November.</li>
<li><strong>2 Nov 2026 – 31 Jan 2027:</strong> gradual fulfilment; ERP or the myDATA special entry form may still be used in parallel.</li>
<li><strong>1 Feb 2027:</strong> licensed provider or AADE timologio / myDATAapp only.</li>
</ul>
<h2>What changes for software</h2>
<ul>
<li><strong>Scope:</strong> domestic wholesale B2B, non-EU wholesale B2B (not retail), and B2G. Retail B2C and intra-EU B2B are outside this decision.</li>
<li><strong>Issue channel:</strong> an AADE-licensed Electronic Tax Document Issuance Provider, or timologio. AADE's FAQ says plainly that ordinary business software (commercial / accounting, ERP) is not an accepted way to issue the e-invoice.</li>
<li><strong>Transmission:</strong> providers post myDATA XML (InvoicesDoc) to the myDATA API and get back a MARK (unique registration number); keep it with the invoice.</li>
<li><strong>Recipient download:</strong> since myDATA v1.0.12 provider invoices carry <code>downloadingInvoiceUrl</code>; recipients can fetch <code>/pdf</code>, <code>/myDATA</code> or <code>/EN16931</code>. Use that URL for the printed QR code.</li>
<li><strong>Penalties:</strong> not issuing an electronic invoice counts as not issuing an invoice (Tax Procedure Code).</li>
</ul>
<h2>Checklist before 2 November 2026</h2>
<ol>
<li>Flag each customer and transaction as in or out of scope.</li>
<li>Integrate at least one licensed provider API, or a clean hand-off to timologio for the smallest users.</li>
<li>Support the start declaration with a start date on or before 2 November 2026.</li>
<li>Store MARK, uid, authenticationCode and the QR URL on every transmitted invoice.</li>
<li>Offer the EN 16931 download for EU buyers who need the European standard, and validate EN 16931 files you generate.</li>
<li>Accept inbound e-invoices for domestic B2B and B2G.</li>
<li>Block "PDF only" for in-scope invoices after the user's obligation date.</li>
</ol>
<h2>Checking the EN 16931 side</h2>
<p>Disclosure: I build W System, an EU e-invoicing and counterparty-check API. It is not a Greek licensed provider and does not transmit to myDATA. What it does help with here: creating and validating the EN 16931 representation (the same European standard behind <code>/EN16931</code>), checking Greek VAT numbers (prefix EL) in VIES before you invoice, and a free in-browser validator at wsystem.dev/e-invoice-validator. The full article, with a live API example and sources, is on wsystem.dev.</p>
<h2>Sources</h2>
<ul>
<li>A.1128/2025 (codified, with A.1197/2026): <a href="https://www.taxheaven.gr/circulars/51018/a-1128-2025">https://www.taxheaven.gr/circulars/51018/a-1128-2025</a></li>
<li>A.1197/2026: <a href="https://www.taxheaven.gr/circulars/55463/a-1197-2026">https://www.taxheaven.gr/circulars/55463/a-1197-2026</a></li>
<li>AADE FAQ (English): <a href="http://www.aade.gr/en/mandatory-electronic-invoicing-digital-goods-movement-documents-frequently-asked-questions-answers">http://www.aade.gr/en/mandatory-electronic-invoicing-digital-goods-movement-documents-frequently-asked-questions-answers</a></li>
<li>myDATA v1.0.12 notes: <a href="https://aade.gr/en/version-v1012">https://aade.gr/en/version-v1012</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Slovakia eFaktúra 2027: what your invoicing software's UBL file must contain]]></title><description><![CDATA[From 1 January 2027 Slovak invoices go over Peppol as BIS 3 UBL. The fields Slovakia requires beyond EN 16931, timeline and checklist.]]></description><link>https://wsystem.hashnode.dev/slovakia-efaktura-2027-ubl-fields</link><guid isPermaLink="true">https://wsystem.hashnode.dev/slovakia-efaktura-2027-ubl-fields</guid><category><![CDATA[ubl]]></category><category><![CDATA[api]]></category><category><![CDATA[peppol]]></category><category><![CDATA[e-invoicing]]></category><category><![CDATA[slovakia ]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Mon, 19 Oct 2026 07:34:17 GMT</pubDate><content:encoded><![CDATA[<p>If you build invoicing or ERP software with Slovak customers, this post gives you the fields that the Slovak Financial Administration (FR SR) requires on top of EN 16931, the dates that matter, how the invoice UUID is formed and a checklist you can work through before 1 January 2027.</p>
<h2>The short version</h2>
<p>From 1 January 2027 Slovak VAT payers must send domestic B2B and B2G invoices as Peppol BIS Billing 3.0 UBL files through a certified provider (digitálny poštár), and every Slovak business must be able to receive them (Act 385/2025 Coll.). A file that passes EN 16931 can still be incomplete for Slovakia: the FR SR transposition spreadsheet v1.12 (14 October 2026) makes several optional EN 16931 fields mandatory.</p>
<h2>Timeline</h2>
<ul>
<li><strong>1 Jan 2026:</strong> Act 385/2025 in force; voluntary e-invoicing through certified providers.</li>
<li><strong>15 Dec 2026:</strong> certified providers must have proven automated reporting.</li>
<li><strong>1 Jan 2027:</strong> issuing e-invoices to Slovak taxable persons is mandatory; everyone must be able to receive; issue within 15 days of the supply.</li>
<li><strong>1 Jan – 30 Jun 2027 (proposal):</strong> no fines for late e-invoices or reporting errors, and buyer-side reporting deleted. Bill 1454 passed first reading on 6 October 2026; it is not law yet.</li>
<li><strong>1 Jul 2030:</strong> EU ViDA stage for cross-border invoices.</li>
</ul>
<h2>How an eFaktúra travels</h2>
<p>Five-corner Peppol model without clearance: your software creates the UBL (C1), the seller's certified provider (C2) sends it to the buyer's provider (C3) and the buyer (C4), and reports tax data to the Financial Administration (C5). No QR code, hash or authority stamp. Every Slovak participant is registered in a central SMP as <code>0245:</code> plus the 10-digit DIČ.</p>
<h2>Fields Slovakia requires beyond EN 16931</h2>
<ul>
<li><strong>BT-34 / BT-49 (seller and buyer electronic address):</strong> mandatory, scheme <code>0245</code> + 10-digit DIČ (the digits after "SK" in the IČ DPH), not 9950 + VAT number.</li>
<li><strong>BT-35/37/38 and BT-50/52/53 (street, city, postal code):</strong> required for both parties (VAT Act s. 74(1)(a)–(b)).</li>
<li><strong>BT-30 / BT-47 (IČO):</strong> give it whenever one has been assigned.</li>
<li><strong>BT-33 (seller legal information):</strong> legal form plus the register entry (court, section, insert number).</li>
<li><strong>BT-7 (tax point date):</strong> required when the supply date is known and differs from the issue date. BT-8 is not used.</li>
<li><strong>BT-121 / BT-120 (VATEX code and reason):</strong> map every exemption to a VATEX code first, with the legal wording as text. 0 € VAT is not automatically category Z.</li>
<li><strong>BT-3:</strong> corrections are a credit note (381) plus a new invoice; type 384 is not recommended yet.</li>
</ul>
<h2>The invoice UUID</h2>
<p>Access points identify each invoice by a UUID version 5 over "BT-34schemeID BT-34 BT-3 BT-1 BT-2" (single spaces, date as YYYY-MM-DD) with the namespace <code>3fd00464-9f15-52ce-8cdc-6dd374d5ad42</code>. The worked example in the FR SR document gives the namespace itself as the output, so compute it with a standard UUIDv5 library and confirm the value with your provider.</p>
<h2>Checklist</h2>
<ol>
<li>Emit Peppol BIS Billing 3.0 UBL for invoices and credit notes.</li>
<li>Store the DIČ of every Slovak party and write <code>EndpointID schemeID="0245"</code>.</li>
<li>Make addresses mandatory for Slovak parties; store IČO and register entry; fill BT-33.</li>
<li>Fill BT-7 when the supply date differs; never send BT-8.</li>
<li>Map exemptions to VATEX codes.</li>
<li>Check whether the customer can already receive (Peppol Directory search for <code>0245:&lt;DIČ&gt;</code>).</li>
<li>Pick a certified provider and run the Slovak tests on the Peppol Testbed.</li>
<li>Validate every outgoing file before it reaches the provider.</li>
</ol>
<h2>Try it on a sample invoice</h2>
<p><em>Disclosure: I'm the maker of the API used here (W System).</em></p>
<p><code>POST https://api.wsystem.dev/einvoice/create</code> turns simple JSON into a Peppol BIS 3 UBL invoice with the 0245:DIČ endpoints, checks it against the official CEN EN 16931 rules and, for Slovak sellers, adds field warnings we wrote from the v1.12 transposition (ruleset SK-FS; our reading, not the official schematron). The free browser validator at <a href="https://wsystem.dev/e-invoice-validator">https://wsystem.dev/e-invoice-validator</a> has a "Load a Slovak example" button. The full request and real response are in <a href="https://wsystem.dev/slovakia-efaktura-2027-invoicing-software">the original article</a>.</p>
<p>Not tax advice; check the current FR SR transposition version before you release.</p>
]]></content:encoded></item><item><title><![CDATA[Germany's BMF letter of 15 October 2026 on e-invoicing: what changes for invoicing software]]></title><description><![CDATA[The third BMF letter on German B2B e-invoicing keeps every deadline but settles down payments, construction invoices, gross prices, corrections and…]]></description><link>https://wsystem.hashnode.dev/bmf-letter-15-october-2026-e-invoicing</link><guid isPermaLink="true">https://wsystem.hashnode.dev/bmf-letter-15-october-2026-e-invoicing</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[Xrechnung]]></category><category><![CDATA[zugferd]]></category><category><![CDATA[Germany]]></category><category><![CDATA[api]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Mon, 19 Oct 2026 07:13:36 GMT</pubDate><content:encoded><![CDATA[<p>The German Federal Ministry of Finance published its third letter on mandatory B2B e-invoicing on 15 October 2026. It moves no deadline and adds no new format, but it answers practical questions every invoicing or ERP product has to handle before issuing becomes mandatory on 1 January 2027.</p>
<h2>The letter in one paragraph</h2>
<p>BMF letter of 15 October 2026 (III C 5 - S 7287-a/00019/021/017) supplements the letters of 15 October 2024 and 15 October 2025 and amends the VAT application decree (UStAE). E-invoices issued until 31 December 2026 that meet the 2024 and 2025 letters but not the new extra requirements will not be objected to, also for input VAT. Source: <a href="https://www.bundesfinanzministerium.de/Content/DE/Downloads/BMF_Schreiben/Steuerarten/Umsatzsteuer/Umsatzsteuer-Anwendungserlass/2026-10-15-obligatorische-elektronische-rechnung.pdf?__blob=publicationFile&amp;v=2">BMF letter (PDF)</a>.</p>
<h2>Deadlines: unchanged</h2>
<ul>
<li>Receiving e-invoices: mandatory since 1 January 2025.</li>
<li>Issuing: from 1 January 2027 for issuers with more than EUR 800,000 prior-year turnover.</li>
<li>Transition for smaller issuers (and certain EDI procedures with consent) ends 31 December 2027.</li>
</ul>
<h2>What changes for software (Rn. = paragraph in the letter)</h2>
<ul>
<li><strong>Final invoices (Rn. 3-4):</strong> until 30 June 2030, deduct received down payments as one sum in BT-113 (Paid amount) with the details in BT-22 (Invoice note), or in an embedded attachment referenced from the structured part.</li>
<li><strong>Down-payment invoices (Rn. 2):</strong> those issued before your obligation starts need not be e-invoices.</li>
<li><strong>Mandatory fields (Rn. 8-9):</strong> use the KoSIT / FeRD mapping of VAT-mandatory items to BT fields.</li>
<li><strong>Service description (Rn. 10-12):</strong> must be meaningful in the XML; timesheets and similar detail can be embedded attachments.</li>
<li><strong>Construction (Rn. 13-14):</strong> trades with sums in the XML plus a human-readable bill-of-quantities attachment.</li>
<li><strong>Gross-price invoices (Rn. 17-19):</strong> until 31 December 2027, totals per VAT rate in the XML and line items in an embedded attachment.</li>
<li><strong>Corrections (Rn. 20-21):</strong> must be e-invoices too; any workable correction method is fine if the result is unambiguous.</li>
<li><strong>Business-rule errors (Rn. 22-23):</strong> technically the file is not EN 16931, but for VAT it is still in principle an e-invoice unless a VAT-mandatory item is affected.</li>
<li><strong>Penalties (Rn. 28):</strong> issuing a PDF instead of a required e-invoice is not an administrative offence under § 26a(2) no. 1 UStG. It is still not compliant.</li>
</ul>
<h2>A checklist before 1 January 2027</h2>
<ol>
<li>Map every VAT-mandatory item to its BT/BG field.</li>
<li>Write BT-113 plus a generated BT-22 note on final invoices.</li>
<li>Always send the delivery date (BT-72) or an invoicing period.</li>
<li>Emit corrections and credit notes as e-invoices.</li>
<li>Support embedded attachments and reference them.</li>
<li>Validate every outgoing file against EN 16931 / XRechnung and report schema errors and business-rule errors separately.</li>
</ol>
<h2>Example: a final invoice with BT-113 and BT-22</h2>
<p><em>Disclosure: I'm the maker of the API used here (W System).</em></p>
<p><code>POST https://api.wsystem.dev/einvoice/create</code> takes simple JSON with <code>prepaid_amount</code> (BT-113) and <code>note</code> (BT-22) and returns an XRechnung checked against the official CEN EN 16931 and KoSIT XRechnung rules. Without a <code>delivery_date</code> it still validates but warns with <code>BR-DE-TMP-32</code>. The full request and the real response are on <a href="https://wsystem.dev/germany-bmf-letter-15-october-2026-e-invoicing">the original article</a>. 20 free calls a day without a key.</p>
<p>Not tax advice; read the letter for the exact wording.</p>
]]></content:encoded></item><item><title><![CDATA[How to validate XRechnung and ZUGFeRD e-invoices against EN 16931 (and four gotchas)]]></title><description><![CDATA[Free official KoSIT validator, tested commands and output, plus a hosted API option]]></description><link>https://wsystem.hashnode.dev/validate-xrechnung-zugferd-en16931</link><guid isPermaLink="true">https://wsystem.hashnode.dev/validate-xrechnung-zugferd-en16931</guid><category><![CDATA[e-invoicing]]></category><category><![CDATA[xml]]></category><category><![CDATA[api]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Sun, 18 Oct 2026 09:01:21 GMT</pubDate><content:encoded><![CDATA[<p>Check XRechnung, ZUGFeRD/Factur-X and Peppol UBL e-invoices against EN 16931 with the free official KoSIT validator, read its results correctly, and avoid four common gotchas.</p>
<p>Germany has required businesses to be able to receive structured EN 16931 e-invoices since January 2025, Belgium made Peppol B2B e-invoicing mandatory in January 2026, and since September 2026 every French business must be able to receive e-invoices too. In practice that means your system will receive XRechnung XML, ZUGFeRD/Factur-X PDFs and Peppol UBL files, and before you book or send one you want to know whether it is actually valid against <strong>EN 16931</strong>, the European e-invoice standard. Here is how to check that with the official rule sets, what the results look like, and four gotchas I hit while testing today.</p>
<h2>The official tools</h2>
<p>Two free, open-source artefacts do the real work:</p>
<ul>
<li><p><strong>EN 16931 validation artefacts</strong> from CEN/TC 434 (Schematron for UBL and CII, EUPL-1.2): <a href="https://github.com/ConnectingEurope/eInvoicing-EN16931">ConnectingEurope/eInvoicing-EN16931</a></p>
</li>
<li><p><strong>KoSIT validator + XRechnung configuration</strong> (Apache-2.0), maintained by the German coordination office for IT standards. The configuration bundles the EN 16931 Schematron, the XRechnung CIUS rules and the UBL 2.1 / CII D16B schemas: <a href="https://github.com/itplr-kosit/validator">itplr-kosit/validator</a> and <a href="https://github.com/itplr-kosit/validator-configuration-xrechnung">itplr-kosit/validator-configuration-xrechnung</a></p>
</li>
</ul>
<h2>Running the KoSIT validator (tested)</h2>
<p>You need Java (I used OpenJDK 21). Download the validator jar and the latest configuration release:</p>
<pre><code class="language-bash">mkdir kosit &amp;&amp; cd kosit
curl -LO https://github.com/itplr-kosit/validator/releases/download/v1.6.3/validator-1.6.3-standalone.jar
curl -LO https://github.com/itplr-kosit/validator-configuration-xrechnung/releases/download/v2026-08-31/xrechnung-3.0.2-validator-configuration-2026-08-31.zip
unzip xrechnung-3.0.2-validator-configuration-2026-08-31.zip -d conf
cd conf
java -jar ../validator-1.6.3-standalone.jar -s scenarios.xml -r ${PWD} -h invoice.xml
</code></pre>
<p><code>-s</code> points at the scenario file (it detects UBL Invoice, UBL CreditNote, CII, XRechnung and so on), <code>-r</code> is the repository folder with the schemas and Schematron, and <code>-h</code> also writes an HTML report next to the XML report (<code>invoice-report.html</code>, <code>invoice-report.xml</code>).</p>
<p>I ran it on two XRechnung 3.0 UBL invoices: a correct one, and a copy where I removed the Buyer reference and changed the payable amount from 1164.25 to 1164.00. The output (trimmed):</p>
<pre><code class="language-plaintext">|File      |Schema |Schematron|Acceptance|Error/Description
|bad.xml   |   Y   |    N     |  REJECT  |[BR-CO-16]-Amount due for payment (BT-115) = Invoice total amount
|          |       |          |          | with VAT (BT-112) -Paid amount (BT-113) +Rounding amount (BT-114).;
|          |       |          |          |[BR-DE-15] Das Element "Buyer reference" (BT-10) muss Ã¼bermittelt werden.
|good.xml  |   Y   |    N     |ACCEPTABLE|[BR-DE-TMP-32] Eine Rechnung sollte zur Angabe des Liefer-/Leistungsdatums
|          |       |          |          | entweder BT-72 "Actual delivery date", BG-14 "Invoicing period" ...
Acceptable:  1  Rejected:  1
</code></pre>
<h2>Gotcha 1: "Schematron N" does not mean rejected</h2>
<p>Look at <code>good.xml</code> above: the Schematron column says <strong>N</strong>, yet the verdict is <strong>ACCEPTABLE</strong>. The column flags any Schematron finding, including warnings. BR-DE-TMP-32 is a warning (no delivery date or invoicing period). Decide on the <strong>Acceptance</strong> column, or on the <code>flag="fatal"</code> entries in the XML report, not on the Schematron column.</p>
<h2>Gotcha 2: XRechnung is stricter than EN 16931</h2>
<p>BR-DE-15 is not an EN 16931 rule, it's an XRechnung rule: German public-sector buyers need the <strong>Buyer reference (BT-10)</strong>, usually the Leitweg-ID. A file can pass plain EN 16931 and still be rejected as XRechnung. The rules that apply are chosen by the <code>CustomizationID</code> in the invoice (for XRechnung 3.0: <code>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</code>), so check which one your generator writes.</p>
<h2>Gotcha 3: the totals must add up exactly</h2>
<p>BR-CO-16 checks that amount due = total with VAT âˆ’ paid amount + rounding amount. Generators that round each line differently from the document total trip this rule (and its neighbours BR-CO-10 to BR-CO-15). Compute totals from the same rounded line net amounts that you write into the file.</p>
<h2>Gotcha 4: ZUGFeRD/Factur-X PDFs need the XML pulled out first</h2>
<p>The KoSIT validator reads XML. A ZUGFeRD or Factur-X invoice is a PDF/A-3 with the CII XML embedded as a file attachment, usually named <code>factur-x.xml</code> (ZUGFeRD 2.1+ and Factur-X), <code>zugferd-invoice.xml</code> (ZUGFeRD 2.0) or <code>xrechnung.xml</code> (XRechnung profile). With <a href="https://pypi.org/project/pypdf/">pypdf</a>:</p>
<pre><code class="language-python">from pypdf import PdfReader

reader = PdfReader("EN16931_Einfach.pdf")
for name, contents in reader.attachments.items():
    print(name, len(contents[0]), "bytes")
    if name.lower() in ("factur-x.xml", "zugferd-invoice.xml", "xrechnung.xml"):
        open("invoice.xml", "wb").write(contents[0])
</code></pre>
<p>On the official ZUGFeRD 2.3 sample <code>EN16931_Einfach.pdf</code> this prints <code>factur-x.xml 13397 bytes</code>, and the extracted file validates as ACCEPTABLE. Note that this only validates the XML; it does not check that the PDF is valid PDF/A-3 or that the visible PDF matches the XML.</p>
<h2>Other practical tips</h2>
<ul>
<li><p><strong>Pin the configuration version.</strong> KoSIT publishes new configuration releases a few times a year as rules change; log which release you validated against so a rejection months later can be reproduced.</p>
</li>
<li><p><strong>Peppol BIS Billing 3.0 has its own extra rules</strong> (<code>PEPPOL-EN16931-*</code>) on top of EN 16931. If you send over Peppol, also run OpenPeppol's rules, which are published separately under their own terms.</p>
</li>
<li><p><strong>Validate what you send, not just what you receive.</strong> Most rejections I've seen come from the sender's own generator (missing BT-10, wrong unit codes, rounding).</p>
</li>
</ul>
<h2>If you'd rather not run Java and keep the rules updated</h2>
<p><em>Disclosure: I'm the maker of the hosted validator below (W System).</em></p>
<p>I built a hosted version as part of the W System EU business data API. It runs the same official EN 16931 and KoSIT XRechnung artefacts (unmodified, sources linked in every response) and accepts UBL, CII or a ZUGFeRD/Factur-X PDF directly:</p>
<pre><code class="language-bash">curl -X POST https://api.wsystem.dev/einvoice/validate \
  -H 'Content-Type: application/xml' --data-binary @bad.xml
</code></pre>
<p>For the broken invoice above it returns the same two errors as the KoSIT run, as JSON (trimmed):</p>
<pre><code class="language-json">{
  "valid": false,
  "error_count": 2,
  "warning_count": 1,
  "syntax": "ubl",
  "profile": "XRechnung",
  "errors": [
    {"rule_id": "BR-CO-16", "ruleset": "EN16931", "severity": "error",
     "business_terms": ["BT-112", "BT-113", "BT-114", "BT-115"]},
    {"rule_id": "BR-DE-15", "ruleset": "XRechnung", "severity": "error",
     "business_terms": ["BT-10"]}
  ],
  "checked": {"xsd": true, "EN16931": true, "XRechnung": true, "PeppolBIS3": false},
  "rule_versions": {"EN16931": "1.3.15+ via KoSIT config", "XRechnung": "3.0.2 config 2026-08-31"}
}
</code></pre>
<p>A PDF works the same way with <code>-H 'Content-Type: application/pdf' --data-binary @invoice.pdf</code>. Two related calls: <code>POST /einvoice/create</code> builds a valid XRechnung or Peppol BIS UBL invoice from plain JSON (try <code>GET /einvoice/sample</code> for the input format), and <code>GET /einvoice/route?id=BE0403170701</code> tells you whether a company is on Peppol and what its country's e-invoicing mandate requires.</p>
<p>Honest limits: Peppol BIS 3 specific rules are <strong>not</strong> checked yet (the response says <code>PeppolBIS3: false</code>), and a technically valid file is not tax advice.</p>
<p>Pricing: 20 free calls per day per IP with no API key or signup. After that, x402 pay-per-call in USDC on Base ($0.03 per validation, $0.08 per created invoice, $0.02 per route lookup), or a monthly plan with an API key (Starter â‚¬19/month for 5,000 units, Pro â‚¬49/month for 25,000 units; a validation uses 3 units). It's also available to AI agents as MCP tools (<code>validate_einvoice</code>, <code>create_einvoice</code>, <code>einvoice_route</code>) on the remote MCP server at <code>https://api.wsystem.dev/mcp/</code>.</p>
<p>Details and docs: <a href="https://wsystem.dev/eu-e-invoice-validation-api">EU e-invoice validation API</a>.</p>
]]></content:encoded></item><item><title><![CDATA[How to validate EU EORI numbers with the official EOS API (and two gotchas)]]></title><description><![CDATA[Validate EU EORI numbers for free with the European Commission's EOS SOAP service: a tested Python example and two gotchas (the 502 on the default…]]></description><link>https://wsystem.hashnode.dev/how-to-validate-eu-eori-numbers-with-the-official-eos-api-and-two-gotchas</link><guid isPermaLink="true">https://wsystem.hashnode.dev/how-to-validate-eu-eori-numbers-with-the-official-eos-api-and-two-gotchas</guid><category><![CDATA[api]]></category><category><![CDATA[Python]]></category><category><![CDATA[logistics]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Sat, 17 Oct 2026 08:59:05 GMT</pubDate><content:encoded><![CDATA[<p>Validate EU EORI numbers for free with the European Commission's EOS SOAP service: a tested Python example and two gotchas (the 502 on the default User-Agent, and GB numbers no longer in EOS).</p>
<p>If you import into or export out of the EU, every customs declaration carries an EORI number (Economic Operators Registration and Identification). Freight forwarders, customs brokers and marketplaces check these numbers when onboarding a shipper, and a typo or a deregistered number means a held shipment. The European Commission runs a free validation service called EOS. It has a web form, but for anything automated you'll want its SOAP API. Here is what works today, including two gotchas that cost me time.</p>
<h2>The endpoint</h2>
<pre><code class="language-plaintext">POST https://ec.europa.eu/taxation_customs/dds2/eos/validation/services/validation
Content-Type: text/xml; charset=utf-8
</code></pre>
<p>No API key, no account. One request can carry <strong>up to 10 EORI numbers</strong>.</p>
<pre><code class="language-bash">curl -s -X POST https://ec.europa.eu/taxation_customs/dds2/eos/validation/services/validation \
  -H 'Content-Type: text/xml; charset=utf-8' \
  -d '&lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;
  &lt;soap:Body&gt;
    &lt;ev:validateEORI xmlns:ev="http://eori.ws.eos.dds.s/"&gt;
      &lt;ev:eori&gt;SE5560360793&lt;/ev:eori&gt;
      &lt;ev:eori&gt;DE1234567&lt;/ev:eori&gt;
    &lt;/ev:validateEORI&gt;
  &lt;/soap:Body&gt;
&lt;/soap:Envelope&gt;'
</code></pre>
<p>The response I got back today (trimmed):</p>
<pre><code class="language-xml">&lt;return&gt;
  &lt;requestDate&gt;17/10/2026&lt;/requestDate&gt;
  &lt;result&gt;
    &lt;eori&gt;SE5560360793&lt;/eori&gt;&lt;status&gt;0&lt;/status&gt;&lt;statusDescr&gt;Valid&lt;/statusDescr&gt;
    &lt;name&gt;SAAB Aktiebolag&lt;/name&gt;&lt;postalCode&gt;58188&lt;/postalCode&gt;
    &lt;city&gt;LINKÖPING&lt;/city&gt;&lt;country&gt;Sweden&lt;/country&gt;
  &lt;/result&gt;
  &lt;result&gt;
    &lt;eori&gt;DE1234567&lt;/eori&gt;&lt;status&gt;1&lt;/status&gt;&lt;statusDescr&gt;Not valid&lt;/statusDescr&gt;
  &lt;/result&gt;
&lt;/return&gt;
</code></pre>
<ul>
<li><p><code>status</code> <strong>0 = valid, 1 = not valid</strong>.</p>
</li>
<li><p>Name and address only appear when the trader agreed to publish them. Many valid numbers come back with no name at all, so don't treat a missing name as a failure.</p>
</li>
<li><p><code>requestDate</code> is the date of the check. Store it alongside the result if you need an audit trail.</p>
</li>
</ul>
<h2>A Python version (tested)</h2>
<pre><code class="language-python">import re
import xml.etree.ElementTree as ET
import requests

EOS_URL = "https://ec.europa.eu/taxation_customs/dds2/eos/validation/services/validation"
NS = "http://eori.ws.eos.dds.s/"

def clean(eori: str) -&gt; str:
    return re.sub(r"[\s.\-]", "", eori).upper()

def check_eoris(eoris):
    """Validate up to 10 EU EORI numbers per call against the EC EOS service."""
    eoris = [clean(e) for e in eoris]
    body = "".join(f"&lt;ev:eori&gt;{e}&lt;/ev:eori&gt;" for e in eoris)
    envelope = (
        '&lt;soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;'
        f'&lt;soap:Body&gt;&lt;ev:validateEORI xmlns:ev="{NS}"&gt;{body}&lt;/ev:validateEORI&gt;'
        "&lt;/soap:Body&gt;&lt;/soap:Envelope&gt;"
    )
    r = requests.post(EOS_URL, data=envelope.encode(),
                      headers={"Content-Type": "text/xml; charset=utf-8",
                               "User-Agent": "my-app-eori-check/1.0"},  # see gotcha below
                      timeout=20)
    r.raise_for_status()
    out = []
    for res in ET.fromstring(r.content).iter("result"):
        item = {child.tag: child.text for child in res}
        item["valid"] = item.get("status") == "0"
        out.append(item)
    return out

if __name__ == "__main__":
    for row in check_eoris(["SE 556036-0793", "DE1234567"]):
        print(row)
</code></pre>
<p>Output:</p>
<pre><code class="language-plaintext">{'eori': 'SE5560360793', 'status': '0', 'statusDescr': 'Valid', 'name': 'SAAB Aktiebolag', ..., 'city': 'LINKÖPING', 'country': 'Sweden', 'valid': True}
{'eori': 'DE1234567', 'status': '1', 'statusDescr': 'Not valid', 'valid': False}
</code></pre>
<p>For more than 10 numbers, chunk the list into groups of 10 and send the chunks with modest concurrency.</p>
<h2>Gotcha 1: the default python-requests User-Agent gets a 502</h2>
<p>This one surprised me. The exact same envelope that works with <code>curl</code> returned <strong>HTTP 502 Bad Gateway</strong> from Python <code>requests</code> every time. The only difference was the User-Agent header: with the library default (<code>python-requests/x.y</code>) the gateway answers 502, and with any other value, like <code>my-app-eori-check/1.0</code>, it answers 200. So if you see 502s from EOS in code but not in your terminal, set a User-Agent before you start debugging the XML.</p>
<h2>Gotcha 2: GB numbers aren't in EOS any more</h2>
<p>Since Brexit, <code>GB...</code> EORIs are validated by HMRC, not the Commission. Northern Ireland traders have an <code>XI...</code> number, which <strong>is</strong> in EOS. HMRC's API is a simple JSON call, also without auth:</p>
<pre><code class="language-bash">curl -s -X POST https://api.service.hmrc.gov.uk/customs/eori/lookup/check-multiple-eori \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/vnd.hmrc.1.0+json' \
  -d '{"eoris":["GB225109100000"]}'
</code></pre>
<p>A robust checker routes by prefix: <code>GB</code> goes to HMRC, everything else (EU-27 plus <code>XI</code>) goes to EOS.</p>
<h2>Other practical tips</h2>
<ul>
<li><p><strong>Clean the input.</strong> People paste <code>SE 556036-0793</code> or <code>de-123.456</code>. Strip spaces, dots and dashes and uppercase it before sending.</p>
</li>
<li><p><strong>Validate the format locally.</strong> An EORI is a two-letter country code followed by up to 15 alphanumeric characters (17 in total at most). Rejecting garbage locally saves calls and gives users instant feedback.</p>
</li>
<li><p><strong>An outage is not "invalid".</strong> EOS has maintenance windows and occasional 5xx errors. Retry with backoff and mark the check as pending, so a customer isn't rejected because Brussels was down.</p>
</li>
<li><p><strong>EORI is not VAT.</strong> In many EU countries the EORI is based on the company's VAT or tax number, but it's a separate registration: a valid VAT number doesn't mean the company has an EORI, and vice versa. Check VAT numbers against VIES separately.</p>
</li>
</ul>
<h2>If you'd rather not maintain the SOAP plumbing</h2>
<p><em>Disclosure: I'm the maker of the EORI checker below (W System).</em></p>
<p>I built two hosted versions of the above, with the input cleaning, format checks, chunking and retries done for you:</p>
<ul>
<li><p><strong>Apify Actor:</strong> <a href="https://apify.com/wsystem/eu-eori-checker">EU EORI Number Checker</a>. Batch up to 1,000 EORIs per run, JSON or CSV out, $0.01 per answered check plus $0.005 per run. Format errors and EOS outages aren't charged. It also works as a tool for AI agents through Apify's MCP server (<code>https://mcp.apify.com/?tools=wsystem/eu-eori-checker</code>).</p>
</li>
<li><p><strong>HTTP API / MCP server:</strong> <code>GET https://api.wsystem.dev/eori?eori=SE5560360793</code> and <code>POST /eori/batch</code>, plus a remote MCP endpoint at <code>https://api.wsystem.dev/mcp/</code> with a <code>verify_eori</code> tool. 20 free calls per day per IP, then pay per call in USDC via x402. Source on <a href="https://github.com/zifengw/eu-business-data-mcp">GitHub</a>.</p>
</li>
</ul>
<p>Either way, the official endpoint above is free and works fine if you'd rather run it yourself.</p>
]]></content:encoded></item><item><title><![CDATA[Screen names against EU, UN, OFAC and UK sanctions lists with one API call]]></title><description><![CDATA[Screen customers, suppliers and payees against the EU, UN, OFAC and UK sanctions lists in one call, what good fuzzy matching needs, and the caveats to…]]></description><link>https://wsystem.hashnode.dev/screen-names-against-eu-un-ofac-and-uk-sanctions-lists-with-one-api-call</link><guid isPermaLink="true">https://wsystem.hashnode.dev/screen-names-against-eu-un-ofac-and-uk-sanctions-lists-with-one-api-call</guid><category><![CDATA[kyc]]></category><category><![CDATA[aml]]></category><category><![CDATA[compliance ]]></category><category><![CDATA[api]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 15 Oct 2026 13:40:46 GMT</pubDate><content:encoded><![CDATA[<p>Screen customers, suppliers and payees against the EU, UN, OFAC and UK sanctions lists in one call, what good fuzzy matching needs, and the caveats to know.</p>
<p>If you onboard customers, suppliers or payees, you need to check them against sanctions lists. The official sources are free: the EU Financial Sanctions consolidated list, the UN Security Council list, OFAC SDN and the UK sanctions list. They come in four different formats, get updated constantly, and the names are spelled inconsistently (transliterations, aliases, word order).</p>
<h2>What good screening needs</h2>
<ul>
<li><p><strong>All relevant lists.</strong> EU businesses usually need at least EU + UN; anyone touching USD needs OFAC too.</p>
</li>
<li><p><strong>Fuzzy matching.</strong> "Sberbank" vs "Sberbank of Russia", Cyrillic vs Latin transliteration.</p>
</li>
<li><p><strong>Scores, not yes/no.</strong> A human should review hits above a threshold.</p>
</li>
<li><p><strong>Disambiguators.</strong> Birth year and country cut down false positives a lot.</p>
</li>
<li><p><strong>Fresh data.</strong> Lists change weekly, sometimes daily.</p>
</li>
</ul>
<h2>One call</h2>
<p><em>Disclosure: I'm the maker of this Actor (W System).</em></p>
<p>The <a href="https://apify.com/wsystem/sanctions-screening">Sanctions Screening Actor</a> refreshes all four lists daily and returns scored matches. $0.005 per screened name.</p>
<pre><code class="language-json">{
  "names": ["Vladimir Putin", "Sberbank", "Example Trading Ltd"],
  "threshold": 85,
  "birthYear": null,
  "country": null,
  "maxMatchesPerName": 5
}
</code></pre>
<pre><code class="language-python">from apify_client import ApifyClient
client = ApifyClient("&lt;APIFY_TOKEN&gt;")
run = client.actor("wsystem/sanctions-screening").call(run_input={"names": ["Sberbank"], "threshold": 85})
for hit in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(hit)
</code></pre>
<p>AI agents can also reach our tools through the hosted API at <a href="https://eu-vat-checker.onrender.com">https://eu-vat-checker.onrender.com</a> (20 free calls/day, then x402 USDC pay-per-call; MCP endpoint at <code>/mcp/</code>).</p>
<h2>Caveats</h2>
<ul>
<li><p>Screening is a signal, not a legal decision. Document how you review hits.</p>
</li>
<li><p>Tune <code>threshold</code>: 85 is a reasonable start, but go lower for high-risk flows.</p>
</li>
<li><p>Re-screen your existing customer base when lists update, not just at onboarding.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Use EU VAT, company-register and tender lookups from n8n, Make, LangChain and Claude (MCP)]]></title><description><![CDATA[Call EU VAT, company-register, tender and sanctions lookups from Claude/Cursor (MCP), n8n, Make and LangChain, with copy-paste config for each. Disclosure…]]></description><link>https://wsystem.hashnode.dev/use-eu-vat-company-register-and-tender-lookups-from-n8n-make-langchain-and-claude-mcp</link><guid isPermaLink="true">https://wsystem.hashnode.dev/use-eu-vat-company-register-and-tender-lookups-from-n8n-make-langchain-and-claude-mcp</guid><category><![CDATA[mcp]]></category><category><![CDATA[AI]]></category><category><![CDATA[n8n]]></category><category><![CDATA[automation]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 15 Oct 2026 13:40:27 GMT</pubDate><content:encoded><![CDATA[<p>Call EU VAT, company-register, tender and sanctions lookups from Claude/Cursor (MCP), n8n, Make and LangChain, with copy-paste config for each.</p>
<p><em>Disclosure: I'm the maker of these Actors (W System).</em></p>
<p>Four Apify Actors: <a href="https://apify.com/wsystem/sanctions-screening">Sanctions Screening</a>, <a href="https://apify.com/wsystem/eu-vat-checker">EU VAT Checker</a>, <a href="https://apify.com/wsystem/european-company-registry">European Company Registry</a>, <a href="https://apify.com/wsystem/eu-tenders-search">EU Tenders Search</a>. Here's how to call them from common tools.</p>
<h2>Claude Desktop / Cursor / any MCP client</h2>
<p>Apify hosts an MCP server that exposes Actors as tools:</p>
<pre><code class="language-json">{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/actors-mcp-server", "--actors", "wsystem/eu-vat-checker,wsystem/european-company-registry,wsystem/eu-tenders-search,wsystem/sanctions-screening"],
      "env": { "APIFY_TOKEN": "&lt;your token&gt;" }
    }
  }
}
</code></pre>
<p>Alternatively, use Apify's hosted server at <a href="https://mcp.apify.com">https://mcp.apify.com</a> (OAuth, no local install). Then ask: <em>"Check whether HU12345678 is a valid VAT number and give me the consultation number."</em></p>
<p>There is also our own hosted HTTP API at <a href="https://eu-vat-checker.onrender.com">https://eu-vat-checker.onrender.com</a> with an MCP endpoint at <code>https://eu-vat-checker.onrender.com/mcp/</code>: 20 free calls/day, then agents pay per call in USDC via x402 (no account needed).</p>
<h2>n8n</h2>
<p>Use the Apify node (or HTTP Request) → <em>Run Actor and get dataset items</em>: <code>POST https://api.apify.com/v2/acts/wsystem~eu-vat-checker/run-sync-get-dataset-items?token=&lt;TOKEN&gt;</code> with the JSON input as body. Typical flow: new invoice in Sheets → VAT check → write status back.</p>
<h2>Make</h2>
<p>Apify app → "Run an Actor" (synchronous) → "Get Dataset Items". Same input JSON.</p>
<h2>LangChain (Python)</h2>
<pre><code class="language-python">from langchain_apify import ApifyActorsTool
vat = ApifyActorsTool("wsystem/eu-vat-checker")
tenders = ApifyActorsTool("wsystem/eu-tenders-search")  # needs APIFY_API_TOKEN env var
# pass [vat, tenders] to your agent's tools
</code></pre>
<p>Pricing is pay-per-result (\(0.01 / VAT check, \)0.008 / company lookup, $0.003 / tender notice), so agents only cost money when they get answers.</p>
]]></content:encoded></item><item><title><![CDATA[Look up European companies from official registers with one API]]></title><description><![CDATA[Which European company registers offer free official data, what each returns, and how to query them (plus GLEIF LEI) through one interface for KYB, CRM…]]></description><link>https://wsystem.hashnode.dev/look-up-european-companies-from-official-registers-with-one-api</link><guid isPermaLink="true">https://wsystem.hashnode.dev/look-up-european-companies-from-official-registers-with-one-api</guid><category><![CDATA[kyc]]></category><category><![CDATA[api]]></category><category><![CDATA[#OpenData]]></category><category><![CDATA[b2b]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 15 Oct 2026 13:40:08 GMT</pubDate><content:encoded><![CDATA[<p>Which European company registers offer free official data, what each returns, and how to query them (plus GLEIF LEI) through one interface for KYB, CRM enrichment and invoice checks.</p>
<p>KYB checks, CRM enrichment and invoice validation all need the same thing: <em>is this company real, active, and what's its official address?</em> Europe has no single register, but many national registers now offer free open data:</p>
<table>
<thead>
<tr>
<th>Country</th>
<th>Register</th>
<th>Identifier</th>
</tr>
</thead>
<tbody><tr>
<td>France</td>
<td>INSEE SIRENE</td>
<td>SIREN/SIRET</td>
</tr>
<tr>
<td>Norway</td>
<td>Brønnøysund</td>
<td>org.nr</td>
</tr>
<tr>
<td>Finland</td>
<td>PRH / YTJ</td>
<td>Y-tunnus</td>
</tr>
<tr>
<td>Czechia</td>
<td>ARES</td>
<td>IČO</td>
</tr>
<tr>
<td>Poland</td>
<td>KRS</td>
<td>KRS number</td>
</tr>
<tr>
<td>Estonia</td>
<td>e-Business Register</td>
<td>registry code</td>
</tr>
<tr>
<td>Any</td>
<td>GLEIF</td>
<td>LEI</td>
</tr>
</tbody></table>
<p>Each has its own API, auth, rate limits and field names. Normalising them is the real work.</p>
<h2>One interface</h2>
<p><em>Disclosure: I'm the maker of this Actor (W System).</em></p>
<p>The <a href="https://apify.com/wsystem/european-company-registry">European Company Registry Lookup Actor</a> queries these registers (plus GLEIF LEI for any country) and returns a common schema: name, ID, status, address, VAT ID, NACE code. Batch input, $0.008 per lookup.</p>
<p>Input is a list of <code>COUNTRY:id-or-name</code> queries:</p>
<pre><code class="language-json">{"queries": ["FR:552032534", "NO:equinor", "CZ:skoda auto"], "maxResultsPerQuery": 3}
</code></pre>
<h2>Practical advice</h2>
<ul>
<li><p>Search by <strong>ID</strong> when you have it; name search is fuzzy and returns several candidates.</p>
</li>
<li><p>Always check <strong>status</strong> (active / dissolved / in liquidation) and not just existence.</p>
</li>
<li><p>Combine with a VIES VAT check for cross-border invoicing (see <a href="https://apify.com/wsystem/eu-vat-checker">EU VAT Checker</a>).</p>
</li>
<li><p>Coverage is limited to the registers listed; for Germany/others GLEIF LEI is the fallback, and only covers companies with an LEI.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Monitor EU public tenders daily with an API (TED, CPV codes, JSON)]]></title><description><![CDATA[Get a daily, filtered feed of EU public tenders from TED by keyword, CPV code and country, as JSON, using the official API or a scheduled job, plus triage…]]></description><link>https://wsystem.hashnode.dev/monitor-eu-public-tenders-daily-with-an-api-ted-cpv-codes-json</link><guid isPermaLink="true">https://wsystem.hashnode.dev/monitor-eu-public-tenders-daily-with-an-api-ted-cpv-codes-json</guid><category><![CDATA[procurement ]]></category><category><![CDATA[api]]></category><category><![CDATA[automation]]></category><category><![CDATA[#OpenData]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 15 Oct 2026 13:39:48 GMT</pubDate><content:encoded><![CDATA[<p>Get a daily, filtered feed of EU public tenders from TED by keyword, CPV code and country, as JSON, using the official API or a scheduled job, plus triage tips.</p>
<p>Every above-threshold public contract in the EU is published on TED (Tenders Electronic Daily), roughly thousands of notices per week. If you sell to the public sector, a daily filtered feed beats manual searching.</p>
<h2>1. Pick your filters</h2>
<ul>
<li><p><strong>CPV codes</strong>: the EU procurement taxonomy. E.g. <code>72000000</code> (IT services), <code>48000000</code> (software), <code>79400000</code> (consulting). Use the top-level code to catch children.</p>
</li>
<li><p><strong>Countries</strong>: ISO codes of buyers you can serve.</p>
</li>
<li><p><strong>Keywords</strong>: in multiple languages: notices are often only in the local language ("software", "Software", "logiciel", "szoftver").</p>
</li>
<li><p><strong>Deadline</strong>: skip notices closing in &lt; 7 days.</p>
</li>
</ul>
<h2>2. Official route</h2>
<p>TED offers a public search API (<code>https://api.ted.europa.eu/v3/notices/search</code>) with an expert query syntax. It works, but you'll handle pagination, the query language and field mapping yourself.</p>
<h2>3. Shortcut: a scheduled Actor</h2>
<p><em>Disclosure: I'm the maker of this Actor (W System).</em></p>
<p>The <a href="https://apify.com/wsystem/eu-tenders-search">EU Public Tenders Search Actor</a> takes keywords, CPV codes, countries and deadline filters and returns clean JSON, with a "new notices only" monitoring mode. $0.003 per notice returned.</p>
<p>Set it up daily:</p>
<ol>
<li>Open the Actor, fill in filters and set <code>onlyNew: true</code>, then save it as a <strong>Task</strong>. Example input:</li>
</ol>
<pre><code class="language-json">{"keywords": ["software", "logiciel"], "cpvCodes": ["72000000"], "countries": ["DE", "FR"], "onlyOpen": true, "onlyNew": true, "maxNotices": 100}
</code></pre>
<ol>
<li><p>Apify Console → <strong>Schedules</strong> → cron <code>0 7 * * 1-5</code> → attach the Task.</p>
</li>
<li><p>Add an <strong>integration</strong> (webhook, Slack, email, Google Sheets, n8n/Make) on "run succeeded".</p>
</li>
</ol>
<h2>4. Triage tips</h2>
<ul>
<li><p>Score by value + CPV match + deadline, and only alert on top hits.</p>
</li>
<li><p>Dedupe on notice ID (publication number).</p>
</li>
<li><p>Keep a "lost/ignored" list to refine keywords monthly.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How to validate EU VAT numbers when VIES is down]]></title><description><![CDATA[Validate EU VAT numbers reliably even when VIES member-state nodes are down: why "could not check" is not "invalid", how to keep the consultation number as…]]></description><link>https://wsystem.hashnode.dev/how-to-validate-eu-vat-numbers-when-vies-is-down</link><guid isPermaLink="true">https://wsystem.hashnode.dev/how-to-validate-eu-vat-numbers-when-vies-is-down</guid><category><![CDATA[vat]]></category><category><![CDATA[api]]></category><category><![CDATA[ecommerce]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[W System]]></dc:creator><pubDate>Thu, 15 Oct 2026 13:39:21 GMT</pubDate><content:encoded><![CDATA[<p>Validate EU VAT numbers reliably even when VIES member-state nodes are down: why "could not check" is not "invalid", how to keep the consultation number as audit proof, and a retry checklist.</p>
<p>VIES (the EU's VAT Information Exchange System) is free and authoritative, but it is a gateway in front of 28 national systems (EU-27 + Northern Ireland "XI"). Individual member-state nodes regularly return <code>MS_UNAVAILABLE</code>, <code>MS_MAX_CONCURRENT_REQ</code> or time out, often during business hours.</p>
<h2>Rule #1: "could not check" is not "invalid"</h2>
<p>Treat these as <em>transient</em>, never as a negative result:</p>
<ul>
<li><code>MS_UNAVAILABLE</code>, <code>SERVICE_UNAVAILABLE</code>, <code>TIMEOUT</code>, <code>MS_MAX_CONCURRENT_REQ</code>, <code>GLOBAL_MAX_CONCURRENT_REQ</code>, HTTP 5xx. Retry with exponential backoff (e.g. 2s, 8s, 30s, then requeue for minutes later). Don't block checkout; apply VAT provisionally or flag the order for review.</li>
</ul>
<h2>Rule #2: keep the consultation number</h2>
<p>If you send your own VAT number as the <em>requester</em>, VIES returns a consultation number (<code>requestIdentifier</code>). Tax authorities accept it as proof that you checked. Store it with the timestamp and raw response.</p>
<h2>Doing it with the official REST API</h2>
<pre><code class="language-bash">curl -s -X POST https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number \
  -H 'Content-Type: application/json' \
  -d '{"countryCode":"DE","vatNumber":"123456789","requesterMemberStateCode":"HU","requesterNumber":"12345678"}'
</code></pre>
<p>Check member-state availability first: <code>GET https://ec.europa.eu/taxation_customs/vies/rest-api/check-status</code>.</p>
<h2>Batch + retries without writing the plumbing</h2>
<p><em>Disclosure: I'm the maker of this Actor (W System).</em></p>
<p>If you'd rather not maintain retry queues, the <a href="https://apify.com/wsystem/eu-vat-checker">EU VAT Number Checker Actor on Apify</a> wraps VIES with automatic retries on outages, batch input, company name/address and the consultation number. It costs $0.01 per answered check (you aren't charged for checks VIES couldn't answer).</p>
<pre><code class="language-python">from apify_client import ApifyClient
client = ApifyClient("&lt;APIFY_TOKEN&gt;")
run = client.actor("wsystem/eu-vat-checker").call(run_input={
    "vatNumbers": ["DE123456789", "HU12345678"],
    "requesterVatNumber": "HU12345678",  # your own VAT no. -&gt; consultation number
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
</code></pre>
<p>Prefer plain HTTP or an AI agent? The same check is on a hosted API at <a href="https://eu-vat-checker.onrender.com">https://eu-vat-checker.onrender.com</a> (20 free calls/day, then pay-per-call in USDC via x402; MCP endpoint at <code>/mcp/</code>).</p>
<h2>Checklist</h2>
<ul>
<li><p>Normalise input (strip spaces/dots, uppercase, Greece = <code>EL</code> not <code>GR</code>).</p>
</li>
<li><p>Validate format locally before calling VIES.</p>
</li>
<li><p>Retry transient errors; never cache them as invalid.</p>
</li>
<li><p>Store consultation number + timestamp.</p>
</li>
<li><p>Re-check long-term B2B customers periodically; numbers get deregistered.</p>
</li>
</ul>
]]></content:encoded></item></channel></rss>