File drop
Hand invoices over as files.
- Not in the sandbox yet
In plain words
File drop is for ERPs that can only write files: they put invoices in a folder, and the service sends results back as files in the same folder. It saves a client from building an API connection. It watches a folder on the machine that runs the service. It is not enabled on the hosted sandbox, and secure file transfer and cloud storage are not built.
An ERP that can only write files can hand invoices over through one folder. The service watches the folder and treats each file as a submission: a JSON file like POST /invoices, an XML file like POST /invoices/xml. Results come back as files in the same folder.
Note
Not in the sandbox yet
File drop watches a local folder. It is not enabled on the hosted sandbox. There is no SFTP and no object storage; either would be built only if a pilot needs it.
Set up
The folder is set when the service is installed. The service checks it once a second, and watches nothing when no folder is set. A file goes through the same intake as an API call, so it is refused for the same reasons.
Name the file
| File | Treated as |
|---|---|
INVOICE-REF.json | POST /invoices. The content is the JSON body of that call (see submit JSON). If the body has an invoice_ref, it must equal the file name without .json. |
INVOICE-REF.ROUTE.xml | POST /invoices/xml. ROUTE is DE-XRECHNUNG, PEPPOL, FR-PA, PL-KSEF or RO-EFACTURA. The content is the invoice file (see submit XML). |
- An invoice reference is up to 100 characters and has no
/or\. - A file over 5 MB is refused.
- A name that starts with a dot, contains
..or fits neither pattern is left alone. - The
Idempotency-Keyis the first 32 characters of the file's SHA-256. Dropping an identical file again is a replay, not a second invoice.
What comes back
drop/
DE-4711.json you write this
status/
DE-4711-1.json one file per status event
DE-4712-error.json the answer to a refused file
done/
DE-4711.json an accepted file moves here
failed/
DE-4712.json a refused file moves hereAn accepted file moves to done/. The invoice's events are written to status/, one file per event, named INVOICE-REF-<sequence>.json. Each is one item of the GET /invoices/{id}/events answer. They carry the invoice's hash and no invoice content.
{
"occurred_at": "2026-10-02T17:17:55.857Z",
"sequence": 1,
"environment": "sandbox",
"invoice_ref": "CAPTURE-JSON-1790961440",
"document_sha256": "3b41395db498666777b74f9f5b9fae82871720304bc25bbb590e25b7b75ea1d4",
"event_id": "evt_200c0def79ed702df81d702f",
"country_route": "DE-XRECHNUNG",
"invoice_number": "CAPTURE-JSON-1790961440",
"status": "validated"
}The events that exist when the file is accepted are written at once. Every later event is written as it arrives, until the invoice reaches a final state (accepted, delivered, rejected, validation_failed, dead_letter or cancelled) or 30 days have passed.
A refused file moves to failed/, and status/INVOICE-REF-error.json holds the answer the API would have given. For a file that is not an invoice, that is the 422 below. Fix the data and drop the file again under the same name.
{
"type": "https://eurinvoice.com/problems/validation-failed",
"title": "The invoice did not pass the checks",
"errors": [
{
"code": "EI-XML-TYPE",
"fix_hint": "Send the invoice itself, in the format agreed for the route.",
"who_fixes": "erp",
"source": "XML-safety",
"message": "The file is not an invoice in a format this route accepts. Please send the invoice in the agreed format."
}
],
"status": 422
}What is not here
- SFTP and object storage.
- A way to read an accepted invoice's
inv_id from the folder. The status files carryinvoice_refandinvoice_number.