getreadystack's picture
Upload index.html with huggingface_hub
c7ef2e7 verified
Raw History Blame Contribute Delete
52.6 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>France E Invoice mentions 2026 — check your french invoices free</title>
<meta name="description" content="Check Factur-X, UBL, and CII invoices for the described French mandatory mentions, including SIREN, VAT key, delivery address, operation category, and totals.">
<style>
:root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
.wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
.bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
.sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
.note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
</style>
<script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
<!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/france-einvoice-reception-lint"></head>
<body>
<div class="wrap">
<h1>France E Invoice mentions 2026 — check your french invoices free</h1>
<p class="lede">Lint Factur-X, UBL and CII invoices for the French mandatory mentions a PDP rejects: SIREN Luhn, FR VAT key, delivery address, operation category, totals. 12 rules, offline. Runs entirely in your browser — nothing is uploaded.</p>
<textarea id="src" spellcheck="false">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"&gt;
&lt;cbc:ID&gt;FA-2026-0921&lt;/cbc:ID&gt;
&lt;cbc:IssueDate&gt;2026-09-02&lt;/cbc:IssueDate&gt;
&lt;cbc:InvoiceTypeCode&gt;380&lt;/cbc:InvoiceTypeCode&gt;
&lt;cbc:Note&gt;Prestation de services. Option pour le paiement de la taxe d'apres les debits.&lt;/cbc:Note&gt;
&lt;cbc:DocumentCurrencyCode&gt;EUR&lt;/cbc:DocumentCurrencyCode&gt;
&lt;cac:AccountingSupplierParty&gt;
&lt;cac:Party&gt;
&lt;cac:PartyName&gt;&lt;cbc:Name&gt;Atelier Voltaire SAS&lt;/cbc:Name&gt;&lt;/cac:PartyName&gt;
&lt;cac:PostalAddress&gt;
&lt;cbc:StreetName&gt;18 rue de Provence&lt;/cbc:StreetName&gt;
&lt;cbc:CityName&gt;Paris&lt;/cbc:CityName&gt;
&lt;cbc:PostalZone&gt;75009&lt;/cbc:PostalZone&gt;
&lt;cac:Country&gt;&lt;cbc:IdentificationCode&gt;FR&lt;/cbc:IdentificationCode&gt;&lt;/cac:Country&gt;
&lt;/cac:PostalAddress&gt;
&lt;cac:PartyTaxScheme&gt;
&lt;cbc:CompanyID&gt;FR12842019051&lt;/cbc:CompanyID&gt;
&lt;cac:TaxScheme&gt;&lt;cbc:ID&gt;VAT&lt;/cbc:ID&gt;&lt;/cac:TaxScheme&gt;
&lt;/cac:PartyTaxScheme&gt;
&lt;cac:PartyLegalEntity&gt;
&lt;cbc:RegistrationName&gt;Atelier Voltaire SAS&lt;/cbc:RegistrationName&gt;
&lt;cbc:CompanyID schemeID="0002"&gt;842019051&lt;/cbc:CompanyID&gt;
&lt;/cac:PartyLegalEntity&gt;
&lt;/cac:Party&gt;
&lt;/cac:AccountingSupplierParty&gt;
&lt;cac:AccountingCustomerParty&gt;
&lt;cac:Party&gt;
&lt;cac:PartyName&gt;&lt;cbc:Name&gt;Groupe Bellecour SA&lt;/cbc:Name&gt;&lt;/cac:PartyName&gt;
&lt;cac:PostalAddress&gt;
&lt;cbc:StreetName&gt;7 quai Saint-Antoine&lt;/cbc:StreetName&gt;
&lt;cbc:CityName&gt;Lyon&lt;/cbc:CityName&gt;
&lt;cbc:PostalZone&gt;69002&lt;/cbc:PostalZone&gt;
&lt;cac:Country&gt;&lt;cbc:IdentificationCode&gt;FR&lt;/cbc:IdentificationCode&gt;&lt;/cac:Country&gt;
&lt;/cac:PostalAddress&gt;
&lt;/cac:Party&gt;
&lt;/cac:AccountingCustomerParty&gt;
&lt;cac:Delivery&gt;
&lt;cbc:ActualDeliveryDate&gt;2026-08-28&lt;/cbc:ActualDeliveryDate&gt;
&lt;/cac:Delivery&gt;
&lt;cac:PaymentTerms&gt;
&lt;cbc:Note&gt;Paiement a 30 jours fin de mois.&lt;/cbc:Note&gt;
&lt;/cac:PaymentTerms&gt;
&lt;cac:TaxTotal&gt;
&lt;cbc:TaxAmount currencyID="EUR"&gt;250.00&lt;/cbc:TaxAmount&gt;
&lt;cac:TaxSubtotal&gt;
&lt;cbc:TaxableAmount currencyID="EUR"&gt;1250.00&lt;/cbc:TaxableAmount&gt;
&lt;cbc:TaxAmount currencyID="EUR"&gt;250.00&lt;/cbc:TaxAmount&gt;
&lt;cac:TaxCategory&gt;&lt;cbc:ID&gt;S&lt;/cbc:ID&gt;&lt;cbc:Percent&gt;20.00&lt;/cbc:Percent&gt;&lt;/cac:TaxCategory&gt;
&lt;/cac:TaxSubtotal&gt;
&lt;/cac:TaxTotal&gt;
&lt;cac:LegalMonetaryTotal&gt;
&lt;cbc:LineExtensionAmount currencyID="EUR"&gt;1250.00&lt;/cbc:LineExtensionAmount&gt;
&lt;cbc:TaxExclusiveAmount currencyID="EUR"&gt;1250.00&lt;/cbc:TaxExclusiveAmount&gt;
&lt;cbc:TaxInclusiveAmount currencyID="EUR"&gt;1512.00&lt;/cbc:TaxInclusiveAmount&gt;
&lt;cbc:PayableAmount currencyID="EUR"&gt;1512.00&lt;/cbc:PayableAmount&gt;
&lt;/cac:LegalMonetaryTotal&gt;
&lt;cac:InvoiceLine&gt;
&lt;cbc:ID&gt;1&lt;/cbc:ID&gt;
&lt;cbc:InvoicedQuantity unitCode="HUR"&gt;25&lt;/cbc:InvoicedQuantity&gt;
&lt;cbc:LineExtensionAmount currencyID="EUR"&gt;1250.00&lt;/cbc:LineExtensionAmount&gt;
&lt;cac:Item&gt;&lt;cbc:Name&gt;Integration PDP - lot 2&lt;/cbc:Name&gt;&lt;/cac:Item&gt;
&lt;cac:Price&gt;&lt;cbc:PriceAmount currencyID="EUR"&gt;50.00&lt;/cbc:PriceAmount&gt;&lt;/cac:Price&gt;
&lt;/cac:InvoiceLine&gt;
&lt;/Invoice&gt;</textarea>
<div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
<div id="out" aria-live="polite"></div>
<div id="paid"><strong>Free here:</strong> Check the invoice XML open in the editor against all 12 rules. <strong>In the editor:</strong> Sweep every invoice in the workspace and write one dated reception-readiness report — that part asks for a licence key. <a href="https://getreadystack.com/api/buy/cl/polar_cl_a6x1aVkUPqSGx38DFlJw68NPUQdMdCYBpENCR47YuFw">Sweep every invoice in the workspace and write one dated report - $29 once</a></div>
<p class="note">Same engine as the VS Code extension, byte for byte.</p>
</div>
<script>var FX_RULES = [
{"id": "bt1_invoice_id", "title": "Invoice number and issue date (BT-1, BT-2)", "sev": "error", "basis": "CGI art. 242 nonies A — sequential number and issue date"},
{"id": "bt24_profile", "title": "EN 16931 / Factur-X profile URN (BT-24)", "sev": "error", "basis": "Factur-X 1.0 profiles; the PDP routes on this URN"},
{"id": "currency_eur", "title": "Currency EUR, or VAT total restated in EUR (BT-111)", "sev": "error", "basis": "CGI art. 289 — VAT amount stated in euro"},
{"id": "seller_siren", "title": "Seller SIREN/SIRET present and Luhn-valid", "sev": "error", "basis": "CGI art. 242 nonies A; SIREN carries a Luhn check digit"},
{"id": "buyer_siren", "title": "Buyer SIREN present and Luhn-valid", "sev": "error", "basis": "Mandatory mention added for the French e-invoicing reform"},
{"id": "fr_vat_key", "title": "FR intra-EU VAT key matches the SIREN", "sev": "error", "basis": "Key = (12 + 3 x (SIREN mod 97)) mod 97"},
{"id": "delivery_address", "title": "Delivery address (BG-15)", "sev": "error", "basis": "Mandatory mention added for the French e-invoicing reform"},
{"id": "delivery_date", "title": "Delivery or supply date (BT-72)", "sev": "error", "basis": "CGI art. 242 nonies A — date of the supply"},
{"id": "operation_category", "title": "Category of operation: goods, services or mixed", "sev": "error", "basis": "Mandatory mention added for the French e-invoicing reform"},
{"id": "debits_option", "title": "Option for VAT on debits, on service invoices", "sev": "warn", "basis": "Mandatory mention added for the French e-invoicing reform"},
{"id": "totals_balance", "title": "BT-109 + BT-110 = BT-112", "sev": "error", "basis": "EN 16931 BR-CO-15"},
{"id": "late_payment_terms", "title": "Late-payment rate and the 40 EUR recovery indemnity", "sev": "error", "basis": "Code de commerce art. L441-10"}
]
;</script>
<script>// France E-Invoice Reception Lint — the brain. Same file runs in Node (the extension) and in the browser (the free web page).
'use strict';
var RULES = (typeof module !== 'undefined') ? require('./rules.json') : window.FX_RULES;
var RECEPTION_DATE = '2026-09-01'; // all French businesses must be able to receive e-invoices from this date
var FINE_PER_MENTION = 15; // CGI art. 1737: 15 EUR per missing or wrong mandatory mention
var FINE_CAP_YEAR = 15000; // annual cap on the per-invoice transmission fine
var LATE_INDEMNITY = 40; // C. com. art. L441-10: 40 EUR fixed recovery indemnity
function leaves(text) {
var out = {}, re = /<(?:[\w.-]+:)?([\w.-]+)\b[^>]*>([^<]*)<\/(?:[\w.-]+:)?\1>/g, m;
while ((m = re.exec(text))) {
var v = m[2].trim();
if (!out[m[1]]) out[m[1]] = [];
out[m[1]].push(v);
}
return out;
}
function block(text, name) {
var re = new RegExp('<(?:[\\w.-]+:)?' + name + '\\b[^>]*>([\\s\\S]*?)<\\/(?:[\\w.-]+:)?' + name + '>', 'i');
var m = re.exec(text);
return m ? m[1] : '';
}
function first(L, names) {
for (var i = 0; i < names.length; i++) {
var v = L[names[i]] || [];
for (var j = 0; j < v.length; j++) if (v[j]) return v[j];
}
return '';
}
function lineOf(text, re) {
var i = text.search(re);
if (i < 0) return 1;
return text.slice(0, i).split('\n').length;
}
function digitsOnly(s) { return String(s || '').replace(/\D/g, ''); }
function luhn(n) {
if (!/^\d+$/.test(n)) return false;
var sum = 0, alt = false;
for (var i = n.length - 1; i >= 0; i--) {
var d = +n[i];
if (alt) { d *= 2; if (d > 9) d -= 9; }
sum += d; alt = !alt;
}
return sum % 10 === 0;
}
function sirenLike(s) { var d = digitsOnly(s); return (d.length === 9 || d.length === 14) ? d : ''; }
function vatKey(siren) {
var k = (12 + 3 * (Number(siren) % 97)) % 97;
return (k < 10 ? '0' : '') + k;
}
function num(s) {
var v = parseFloat(String(s || '').replace(/\s| /g, '').replace(',', '.'));
return isFinite(v) ? v : null;
}
function eur(n) { return n.toFixed(2).replace('.', ',') + ' EUR'; }
function partyIds(text, ublName, ciiName) {
var b = block(text, ublName) || block(text, ciiName);
if (!b) return { found: false, ids: [], block: '' };
var L = leaves(b), ids = [];
['CompanyID', 'ID', 'EndpointID'].forEach(function (k) {
(L[k] || []).forEach(function (v) { var d = sirenLike(v); if (d) ids.push(d); });
});
return { found: true, ids: ids, block: b };
}
function check(text, opts) {
text = String(text == null ? '' : text);
opts = opts || {};
var today = /^\d{4}-\d{2}-\d{2}$/.test(opts.today || '') ? opts.today : new Date().toISOString().slice(0, 10);
var F = [], L = leaves(text);
function add(id, sev, msg, line) { F.push({ check: id, sev: sev, msg: msg, line: line || 1 }); }
if (!/</.test(text)) {
add('bt1_invoice_id', 'error', 'No XML found. Paste the Factur-X, UBL or CII invoice, not the PDF cover page.', 1);
return { findings: F, rule_count: RULES.length, today: today, reception_date: RECEPTION_DATE };
}
// 1 — BT-1 invoice number, BT-2 issue date, and the date must not be later than the as-of date
var head = block(text, 'ExchangedDocument');
var docId = head ? first(leaves(head), ['ID']) : ((/<(?:[\w.-]+:)?ID\b[^>]*>([^<]*)</.exec(text) || [])[1] || '').trim();
var issued = (first(L, ['IssueDate', 'DateTimeString', 'IssueDateTime']).match(/\d{4}-?\d{2}-?\d{2}/) || [''])[0].replace(/(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
if (!docId) add('bt1_invoice_id', 'error', 'BT-1 invoice number is missing. A PDP rejects an invoice with no number.', 1);
else if (!issued) add('bt1_invoice_id', 'error', 'BT-2 issue date is missing next to invoice ' + docId + '.', lineOf(text, /IssueDate/i));
else if (issued > today) add('bt1_invoice_id', 'error', 'BT-2 issue date ' + issued + ' is later than the as-of date ' + today + '. Post-dated invoices are refused.', lineOf(text, /IssueDate/i));
// 2 — BT-24 profile identifier
var ctx = block(text, 'GuidelineSpecifiedDocumentContextParameter');
var prof = first(L, ['CustomizationID']) || (ctx ? first(leaves(ctx), ['ID']) : '');
if (!prof) add('bt24_profile', 'error', 'BT-24 profile identifier is missing. France routes on the Factur-X / EN 16931 profile URN; without it the PDP cannot decide the flow.', 1);
else if (!/en16931|factur-x|facturx|urn:cen\.eu/i.test(prof)) add('bt24_profile', 'error', 'BT-24 is "' + prof + '", which is not an EN 16931 or Factur-X profile URN.', lineOf(text, /CustomizationID|GuidelineSpecified/i));
else if (/minimum|basic ?wl/i.test(prof)) add('bt24_profile', 'warn', 'Profile ' + prof + ' carries no invoice lines. Use BASIC or higher so the buyer can post the invoice.', lineOf(text, /CustomizationID|GuidelineSpecified/i));
// 3 — currency: EUR, or the VAT total restated in EUR (BT-111)
var cur = (first(L, ['DocumentCurrencyCode', 'InvoiceCurrencyCode']) || '').toUpperCase();
var eurTax = first(L, ['TaxAmountInAccountingCurrency', 'TaxTotalAmountInAccountingCurrency', 'TaxCurrencyCode']);
if (!cur) add('currency_eur', 'error', 'Document currency is missing. A French invoice states its currency.', 1);
else if (cur !== 'EUR' && !eurTax) add('currency_eur', 'error', 'Currency is ' + cur + ' and the VAT total is not restated in EUR (BT-111). French law wants the VAT amount in euro.', lineOf(text, /CurrencyCode/i));
// 4 — seller SIREN / SIRET
var sell = partyIds(text, 'AccountingSupplierParty', 'SellerTradeParty');
if (!sell.found) add('seller_siren', 'error', 'No seller party block. The seller SIREN is a mandatory mention.', 1);
else if (!sell.ids.length) add('seller_siren', 'error', 'Seller SIREN (9 digits) or SIRET (14) is missing from the seller party.', lineOf(text, /AccountingSupplierParty|SellerTradeParty/i));
else if (!luhn(sell.ids[0])) add('seller_siren', 'error', 'Seller identifier ' + sell.ids[0] + ' fails its Luhn check digit, so it is not a real SIREN.', lineOf(text, /AccountingSupplierParty|SellerTradeParty/i));
// 5 — buyer SIREN: one of the four mentions France added for the reform
var buy = partyIds(text, 'AccountingCustomerParty', 'BuyerTradeParty');
if (!buy.found) add('buyer_siren', 'error', 'No buyer party block. The buyer SIREN is a mandatory mention.', 1);
else if (!buy.ids.length) add('buyer_siren', 'error', 'Buyer SIREN is missing. France added the buyer SIREN to the mandatory mentions for the e-invoicing reform; the name and address alone are not enough.', lineOf(text, /AccountingCustomerParty|BuyerTradeParty/i));
else if (!luhn(buy.ids[0])) add('buyer_siren', 'error', 'Buyer identifier ' + buy.ids[0] + ' fails its Luhn check digit, so it is not a real SIREN.', lineOf(text, /AccountingCustomerParty|BuyerTradeParty/i));
// 6 — FR intra-EU VAT number: the two-character key is computed from the SIREN
var vats = text.match(/FR[\s]?[0-9A-Z]{2}[\s]?\d{9}/gi) || [];
if (!vats.length) add('fr_vat_key', 'error', 'No French intra-EU VAT number (FR + 2-character key + 9-digit SIREN) anywhere in the invoice.', 1);
else {
var bad = null;
for (var i = 0; i < vats.length; i++) {
var v = vats[i].replace(/\s/g, '').toUpperCase(), k = v.slice(2, 4), s = v.slice(4);
if (/^\d{2}$/.test(k) && k !== vatKey(s)) { bad = { v: v, k: k, want: vatKey(s), s: s }; break; }
}
if (bad) add('fr_vat_key', 'error', 'VAT number ' + bad.v + ' has key ' + bad.k + '. The key computed from SIREN ' + bad.s + ' is ' + bad.want + '.', lineOf(text, /FR[\s]?[0-9A-Z]{2}[\s]?\d{9}/i));
}
// 7 — delivery address (BG-15), another mention France added
var del = block(text, 'Delivery') || block(text, 'ShipToTradeParty');
var delAddr = del && /Address|PostalTradeAddress|CountryCode|CityName|PostalZone/i.test(del);
if (!del) add('delivery_address', 'error', 'Delivery address is missing. France added "adresse de livraison" to the mandatory mentions; the billing address does not stand in for it.', 1);
else if (!delAddr) add('delivery_address', 'error', 'The delivery block carries no address. France added "adresse de livraison" to the mandatory mentions; a date alone is not the address.', lineOf(text, /<(?:[\w.-]+:)?Delivery\b|ShipToTradeParty/i));
// 8 — delivery / supply date (BT-72)
if (!/ActualDeliveryDate|ActualDeliverySupplyChainEvent/i.test(text)) add('delivery_date', 'error', 'BT-72 delivery or supply date is missing. It sets the VAT due date, so the buyer cannot post the invoice without it.', 1);
// 9 — category of operation: goods, services, or mixed
var hasCat = /livraison de biens|prestation[s]? de services?|op[ée]ration[s]? mixte/i.test(text);
if (!hasCat) add('operation_category', 'error', 'Category of operation is missing. State "livraison de biens", "prestation de services" or "operations mixtes" — France added this mention for the reform.', 1);
// 10 — option to account for VAT on debits, for service invoices
var isService = /prestation[s]? de services?|op[ée]ration[s]? mixte/i.test(text);
if ((isService || !hasCat) && !/d'?apr[eè]s les d[ée]bits/i.test(text))
add('debits_option', 'warn', 'A service invoice that has taken the option must print "Option pour le paiement de la taxe d\'apres les debits". Without it the buyer deducts VAT on payment, not on invoice.', 1);
// 11 — totals reconcile: BT-109 + BT-110 = BT-112
var net = num(first(L, ['TaxExclusiveAmount', 'TaxBasisTotalAmount']));
var vat = num(first(L, ['TaxAmount', 'TaxTotalAmount']));
var gross = num(first(L, ['TaxInclusiveAmount', 'GrandTotalAmount']));
if (net === null || vat === null || gross === null) add('totals_balance', 'error', 'One of BT-109 (net), BT-110 (VAT) or BT-112 (total with VAT) is missing, so the totals cannot be reconciled.', 1);
else if (Math.abs(net + vat - gross) > 0.01)
add('totals_balance', 'error', 'Totals do not reconcile: ' + eur(net) + ' + ' + eur(vat) + ' = ' + eur(net + vat) + ', but BT-112 says ' + eur(gross) + ' — off by ' + eur(Math.abs(net + vat - gross)) + '.', lineOf(text, /TaxInclusiveAmount|GrandTotalAmount/i));
// 12 — late payment penalty rate and the fixed recovery indemnity
var hasRate = /p[ée]nalit[ée]s? de retard/i.test(text) && /\d+([.,]\d+)?\s*%/.test(text);
var hasIndem = /indemnit[ée] forfaitaire/i.test(text) && /\b40\b/.test(text);
if (!hasRate || !hasIndem)
add('late_payment_terms', 'error', 'Late-payment mentions are incomplete' + (hasRate ? '' : ' (no penalty rate)') + (hasIndem ? '' : ' (no ' + LATE_INDEMNITY + ' EUR recovery indemnity)') + '. Code de commerce art. L441-10 requires both on every B2B invoice.', 1);
return {
findings: F, rule_count: RULES.length, today: today, reception_date: RECEPTION_DATE,
fine_per_mention: FINE_PER_MENTION, fine_cap_year: FINE_CAP_YEAR
};
}
var API = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
if (typeof module !== 'undefined') module.exports = API;
if (typeof window !== 'undefined') window.FXENGINE = API;
</script>
<script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
'use strict';
function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;'); }
function summaryLine(res) {
const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
}
function toText(res, label) {
const f = (res && res.findings) || [];
const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
return lines.join('\n');
}
function toHtml(res) {
const f = (res && res.findings) || [];
if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
}
var FXREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
if (typeof module !== 'undefined' && module.exports) module.exports = FXREPORT;
else window.FXREPORT = FXREPORT;
</script>
<script>
(function(){
var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
today.value=new Date().toISOString().slice(0,10);
function run(){ try { var res=window.FXENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.FXREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
go.onclick=run; if (src.value.trim()) run();
})();
</script>
<section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://marketplace.visualstudio.com/items?itemName=ReadyStack.france-einvoice-reception-lint" rel="noopener" data-yj-install-door="mp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'france-einvoice-reception-lint',src:'mp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">VS Code Marketplace</a><a href="https://open-vsx.org/extension/readystack/france-einvoice-reception-lint" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'france-einvoice-reception-lint',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><a href="https://www.npmjs.com/package/@readystack/france-einvoice-reception-lint" rel="noopener" data-yj-install-door="npm" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'france-einvoice-reception-lint',src:'npm',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">npm</a><a href="https://www.npmjs.com/package/@readystack/france-einvoice-reception-lint" rel="noopener" data-yj-install-door="mcp" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'france-einvoice-reception-lint',src:'mcp',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">MCP server (npx)</a><a href="https://hub.docker.com/r/getreadystack/france-einvoice-reception-lint" rel="noopener" data-yj-install-door="docker" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'france-einvoice-reception-lint',src:'docker',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Docker Hub</a><pre style="margin:.5rem 0 0;padding:.6rem .8rem;background:#f3f5f8;border-radius:8px;font-size:.9rem;overflow:auto">ext install ReadyStack.france-einvoice-reception-lint
npx @readystack/france-einvoice-reception-lint &lt;file&gt;
npx @readystack/france-einvoice-reception-lint --mcp</pre><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/cl/polar_cl_l6iN1uWt0FwWu7tBsczD0jWpP2vxFM54Wdwqb3KPi1G" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
<section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get the full rule table as a PDF</b><div style="opacity:.78;margin:.35rem 0 .8rem">All 12 rules France E-Invoice Reception Lint checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Email me the PDF</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">Sent. It arrives within the hour - check spam too.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"france-einvoice-reception-lint",lang:"en",source:"rule_table"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);})();</script></section>
<section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the complete version <span class="yj-price">$29</span></h2><p style="margin:.25rem 0 1rem;color:#41505f">This page is the working piece. The full pack has everything below.</p><p style="margin:0 0 1rem;color:#41505f">12 checks for the French mandatory mentions a PDP rejects, on Factur-X, UBL and CII invoices</p><p style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">An e-invoicing integrator bills about 95 US dollars an hour to map and re-test one invoice profile</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_a6x1aVkUPqSGx38DFlJw68NPUQdMdCYBpENCR47YuFw" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
<!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;"}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div>
<script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
<script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script>
<section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-17">Updated 2026-09-17</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-17","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku52828_result_card.jpg" alt="6 rejects in one French invoice" loading="lazy" style="max-width:100%;border-radius:6px"></p>
<p>6 rejects in one French invoice - for billing developers and ERP integrators who emit invoice XML for France. This is what the lint printed on a file that validates as UBL:</p>
<p>L1 bt24_profile BT-24 profile identifier is missing. France routes on the Factur-X / EN 16931 profile URN; without it the PDP cannot decide the flow. L20 fr_vat_key VAT number FR12842019051 has key 12. The key computed from SIREN 842019051 is 43. L29 buyer_siren Buyer SIREN is missing. France added the buyer SIREN to the mandatory mentions for the e-invoicing reform; the name and address alone are not enough. L40 delivery_address The delivery block carries no address. France added &quot;adresse de livraison&quot; to the mandatory mentions; a date alone is not the address. L57 totals_balance Totals do not reconcile: 1250,00 EUR + 250,00 EUR = 1500,00 EUR, but BT-112 says 1512,00 EUR - off by 12,00 EUR. L1 late_payment_terms Late-payment mentions are incomplete (no penalty rate) (no 40 EUR recovery indemnity). Code de commerce art. L441-10 requires both on every B2B invoice.</p>
<p>Six findings, out of 12 checks, on one file generated by a billing template in Paris. The XML is valid. It would have been refused anyway.</p>
<p>Since 1 September 2026, every business established in France must be able to receive an electronic invoice. Issuing is being phased in; reception is not. From that date a supplier can push a Factur-X, UBL or CII document at your platform, and it has to take it and post it.</p>
<p>That is where generated code breaks. A mapping written by an AI assistant, or ported from a German XRechnung integration, validates against EN 16931 and is still refused in France: France added four mandatory mentions on top of the European model. The buyer&#x27;s SIREN, because name and address are not enough. The delivery address, BG-15, which the billing address does not stand in for. The category of the operation: goods, services or mixed. And, on service invoices that took the option, the line &quot;Option pour le paiement de la taxe d&#x27;apres les debits&quot;, which sets when the buyer deducts VAT. A European validator knows none of the four.</p>
<p>Then the arithmetic, the part a chatbot cannot do for you. A SIREN is nine digits carrying a Luhn check digit, so a transposed pair passes a regex and fails the platform. The French intra-EU VAT number carries a two-character key computed from the SIREN as (12 + 3 x (SIREN mod 97)) mod 97 - in the file above, the number carries key 12 where the SIREN 842019051 computes 43. And BT-109 plus BT-110 has to equal BT-112: the file says 1512 where 1250 net and 250 VAT give 1500, off by 12 EUR. A general assistant will not recompute any of those three on a number it has never seen; the platform recomputes all three before it accepts the file.</p>
<p>A reject does not fail quietly either. CGI article 1737 fines 15 EUR per missing or wrong mandatory mention, capped at 15000 EUR a year, and every refused invoice comes back to a human to re-issue.</p>
<p>France E-Invoice Reception Lint is a VS Code extension that runs those 12 checks - eleven errors and one warning - on the XML in front of you, reporting each with a line number, exactly as printed above. It runs offline and uploads nothing. The rule table is plain JSON, and the same engine file runs the free web page, so you can paste an invoice into a browser before installing anything. The deadline is not coming: it arrived on 1 September 2026. The open question is whether the XML your code emits today survives the trip.</p>
<p>Checking the file open in your editor is free and needs no key, and it is a finished job: every finding on that file, not a teaser. The licensed part is scope rather than depth - sweep every invoice in the workspace and write one dated reception-readiness report. Same 12 rules, more files. That is 29 US dollars once, against about 95 US dollars an hour for an integrator to map and re-test one invoice profile, with a 7-day full refund.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku52828_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku52828_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does France E-Invoice Reception Lint actually do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads a Factur-X, UBL or CII invoice XML open in your editor and runs 12 checks for the mentions a French platform rejects on. It verifies the Luhn check digit of the seller and buyer SIREN, recomputes the FR intra-EU VAT key from the SIREN, re-adds BT-109 plus BT-110 against BT-112, and reports every failure with a line number.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Developers who generate invoice XML for French companies: billing engineers at SaaS vendors invoicing France, ERP and accounting-software integrators wiring up a PDP, and teams porting a German XRechnung mapping to France. If you have never had to print the 40 EUR recovery indemnity on an invoice, this is the tool that tells you that you must.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why is a chatbot or a free EN 16931 validator not enough?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A free EN 16931 validator checks the European semantic model. France added mandatory mentions on top of it: the buyer SIREN, the delivery address, the category of operation, and the VAT-on-debits option. A chatbot will list those mentions but will not recompute a Luhn check digit, a mod-97 VAT key, or your totals — and a PDP recomputes all three.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs a licence key?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Free, with no key: check the invoice open in the editor against all 12 rules and get every finding with its line number. That is a complete answer for that file. The licensed part is scope, not depth: sweep every invoice in the workspace and write one dated reception-readiness report. Same rules, more files.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What would this cost me otherwise?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">An e-invoicing integrator bills about 95 US dollars an hour to map and re-test one invoice profile, and a rejected invoice comes back for a human to re-issue. CGI article 1737 fines 15 EUR per missing or wrong mandatory mention, with an annual cap of 15000 EUR. The licence is 29 US dollars once.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just ask ChatGPT or another AI chat?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. France E-Invoice Reception Lint checks the file you open against 12 rules, each naming its legal or official basis, from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does France E-Invoice Reception Lint actually do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads a Factur-X, UBL or CII invoice XML open in your editor and runs 12 checks for the mentions a French platform rejects on. It verifies the Luhn check digit of the seller and buyer SIREN, recomputes the FR intra-EU VAT key from the SIREN, re-adds BT-109 plus BT-110 against BT-112, and reports every failure with a line number."}}, {"@type": "Question", "name": "Who is this for?", "acceptedAnswer": {"@type": "Answer", "text": "Developers who generate invoice XML for French companies: billing engineers at SaaS vendors invoicing France, ERP and accounting-software integrators wiring up a PDP, and teams porting a German XRechnung mapping to France. If you have never had to print the 40 EUR recovery indemnity on an invoice, this is the tool that tells you that you must."}}, {"@type": "Question", "name": "Why is a chatbot or a free EN 16931 validator not enough?", "acceptedAnswer": {"@type": "Answer", "text": "A free EN 16931 validator checks the European semantic model. France added mandatory mentions on top of it: the buyer SIREN, the delivery address, the category of operation, and the VAT-on-debits option. A chatbot will list those mentions but will not recompute a Luhn check digit, a mod-97 VAT key, or your totals — and a PDP recomputes all three."}}, {"@type": "Question", "name": "What is free and what needs a licence key?", "acceptedAnswer": {"@type": "Answer", "text": "Free, with no key: check the invoice open in the editor against all 12 rules and get every finding with its line number. That is a complete answer for that file. The licensed part is scope, not depth: sweep every invoice in the workspace and write one dated reception-readiness report. Same rules, more files."}}, {"@type": "Question", "name": "What would this cost me otherwise?", "acceptedAnswer": {"@type": "Answer", "text": "An e-invoicing integrator bills about 95 US dollars an hour to map and re-test one invoice profile, and a rejected invoice comes back for a human to re-issue. CGI article 1737 fines 15 EUR per missing or wrong mandatory mention, with an annual cap of 15000 EUR. The licence is 29 US dollars once."}}, {"@type": "Question", "name": "Why not just ask ChatGPT or another AI chat?", "acceptedAnswer": {"@type": "Answer", "text": "A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. France E-Invoice Reception Lint checks the file you open against 12 rules, each naming its legal or official basis, from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:52828,slug:"france-einvoice-reception-lint",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/einvoice-mandate-lint"><span class="yj-rel-t">E-Invoice Mandate Lint - EU 2026</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/en16931-einvoice-lint"><span class="yj-rel-t">EN 16931 e-Invoice Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/myinvois-field-check"><span class="yj-rel-t">MyInvois Field Check — Malaysia e-Invoice (UBL 2.1)</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/belgium-einvoice-fine-vs-deduction-2026"><span class="yj-rel-t">Belgium E-Invoice Fine &amp; 120% Check 2026</span><span class="yj-rel-p">$60</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/dashboard-ui-kit-eu-vat-billing"><span class="yj-rel-t">Dashboard UI Kit for EU SaaS Billing — VAT ID, Reverse Charge &amp; OSS States (Fi</span><span class="yj-rel-p">$168</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/saas-dashboard-ui-kit-cancel-button"><span class="yj-rel-t">SaaS Dashboard UI Kit — Cancel Button §312k BGB &amp; Billing Screens (Figma)</span><span class="yj-rel-p">$168</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body>
</html>