The first batch is always the worst. You submit two hundred invoices, a hundred and forty come back rejected, and the messages are terse enough that the natural conclusion is that the format is broken.
The format is fine. What follows is where they actually come from, in the order you will meet them.
1. Units of measure
The single most common rejection, by a distance.
Units come from a controlled list, UN/ECE Recommendation 20. H87 is piece. KGM is kilogram. MTR is metre. LTR is litre. HUR is hour. What is not on the list is buc, kg, ore, set, serviciu, or any of the other perfectly sensible things a Romanian invoicing system has been printing for fifteen years.
The fix is a mapping table, not a find and replace. Build it once, from the distinct values actually present in your data, and have somebody from the business confirm each one. The subtle failures live here: a company using buc for both physical pieces and service units will map both to H87 and lose a distinction they cared about.
For services with no natural unit, C62 (one) or HUR where you genuinely bill hours. Do not invent.
2. VAT category codes and exemption reasons
Every line needs a VAT category code. Standard rate, zero rate, exempt, reverse charge, not subject. And where the category is anything other than standard, it needs a reason, and the reason has to be consistent with the category.
This is where systems that store VAT as a number fall over. 0 is not information. Zero because the customer is an intra-community business, zero because the supply is exempt, and zero because it is reverse charge are three different documents to a validator and identical in most databases.
If you take one thing from this article: store the tax treatment, not the tax rate. The rate is derived from the treatment. Doing it the other way round is lossy, and the loss only becomes visible at the border.
3. Partner identification
The CUI, and specifically whether it carries the RO prefix.
A VAT-registered Romanian company is identified with the prefix. A company that is not VAT registered has a fiscal code without it. Both are valid; using the wrong one for a given partner is a rejection. And the source of truth for which is which is not your database, it is the VAT register, which changes without telling you when a partner registers or deregisters.
So this is not a one-off cleanup. It is a lookup you should be doing at invoice time, against the public register, cached for a sensible period. Most systems discover this the month after a client deregisters.
The related trap: a CUI has a check digit. Validating it before it reaches your database costs nothing and catches typos at the point they are made rather than at the point they are filed.
4. Addresses and county codes
The county is a code from a controlled list, not the county name typed in. Bucharest sectors are their own case and are frequently entered as part of the street line, where the validator cannot see them.
Postal codes are less strict but worth cleaning at the same time, because you are already in the customer table.
5. Totals that do not agree
The document totals must equal the sum of the lines, exactly, at two decimals. This produces the most confusing rejection of the six, because both numbers are individually correct and the difference is usually one ban.
That happens when the invoice total is computed independently of the lines rather than derived from them, and the two paths round differently. It is worth understanding properly, so it has its own article.
6. Document type and references
Credit notes need to reference the invoice they correct. Advance payment invoices and their final settlement need to relate to each other. Getting these structurally right is less about validation and more about what happens afterwards: an unreferenced credit note passes validation and then confuses everybody downstream, including your accountant, for a year.
The thing all six have in common
None of them are XML problems. Every one is a piece of business data that was adequate for printing a PDF and is not adequate for being machine-checked by the state.
Which means the work is not really an integration. It is a data project with an integration at the end, and the ratio is roughly four to one. An estimate that does not say so is either inexperienced or is quietly planning to hand you the cleanup halfway through, at which point it becomes your problem on their timeline.
How to actually do the first run
Do not submit two hundred invoices. Submit one, of each shape you issue: a domestic standard-rate sale, an intra-community supply, a reverse charge, a credit note, an advance, a service with no physical unit. Six documents, in the test environment, until every one comes back accepted.
Every rejection in that set is worth a mapping rule. Every rejection in a batch of two hundred is worth a headache and a spreadsheet.
Then run the whole back catalogue through validation without submitting, purely to see the distribution of failures. That report is the actual project plan, and it takes an afternoon to produce. Almost nobody does it first, and it is the single highest-leverage hour in the whole piece of work. See the wider account of the integration for what surrounds it.
