Docs
4

Statuses

Status events and queue states.

  • In the sandboxevent shape
  • Not in the sandbox yetrail statuses

In plain words

Every invoice has a state, such as queued or rejected, and a history of events that says what happened to it. This is how a client or partner finds out whether an invoice went through. The hosted sandbox holds no rail credential yet, so the events that come from a country connection appear only when a route is connected.

An invoice has two kinds of status. Status events say what happened to it. The queue state says where it is now.

Queue state

GET /invoices/{id} returns the state.

StateMeaning
receivedThe invoice was accepted at intake.
validatedThe invoice passed every check.
validation_failedThe official rules refused the document. It goes to the care list.
source_errorThe ERP data could not be read.
queuedAccepted and waiting.
submittingA send was tried and its answer was lost, so the route may hold the invoice. The worker settles it as submitted or dead_letter.
submittedThe route has the invoice.
readyGermany's final state. The XRechnung or ZUGFeRD is validated and stored for the partner to deliver. Nothing was sent.
acceptedThe route accepted it.
deliveredThe invoice reached the buyer's side.
rejectedThe route refused it for good. It goes to the care list.
dead_letterTransient failures used up their retries. It goes to the care list.
cancelledStopped before submission (see cancel).

queued and submitting are internal steps between validated and submitted, and no status event reports them.

Status events

All routes use the same event shape. GET /invoices/{id}/events returns them, and a webhook delivers the same body (see webhooks).

StatusMeaning
receivedThe invoice was accepted at intake.
validatedThe invoice passed every check.
source_errorThe ERP data could not be read. Carries errors.
validation_failedA check failed. Carries errors.
submittedThe route has the invoice.
acceptedThe route accepted it. Carries legal_id, the route's own reference.
rejectedThe route refused it. Carries errors.
deliveredThe invoice reached the buyer's side.
buyer_statusThe buyer answered. buyer_status is one of acknowledged, in_process, under_query, conditionally_accepted, rejected, approved, disputed or paid.

Fields on every event: event_id, sequence, occurred_at, invoice_ref, invoice_number, country_route, environment, status and document_sha256. Some events add legal_id, buyer_status, errors (the same items as a dry-run finding) and route, which holds the route's submission_id and its native status in raw.

Tip

Order events by sequence, not by time.

The schema enforces three rules: accepted carries legal_id, the three failure statuses carry errors, and buyer_status carries a buyer_status.

Which events occur

In the sandboxsandbox

Intake writes received, with sequence 1. The service then runs the route's validators and writes validated, or validation_failed when a check fails. After that each move of the invoice writes one event: submitted, accepted, delivered or rejected. For Germany nothing follows validated, because the invoice ends at ready. See the recorded events for an example.

On the hosted sandbox no rail credential is stored yet. A route that needs one reaches submitted without anything being sent, and Germany ends at ready. In production a route with no credential retries and then dead-letters the invoice.

Not in the sandbox yetrail statuses

The events that come from a rail (accepted, delivered and buyer_status) need a connected route. The mapping from each rail's own statuses is built and tested, and has run against the test systems of KSeF, a Peppol access point and a French platform. It is not connected on the hosted sandbox yet.

Final status by route

Not in the sandbox yetrails
RouteFinal statusWhat it carriesFailure
PL-KSEFacceptedThe KSeF number as legal_id.rejected with the KSeF code, for example KSEF-440 for a duplicate.
RO-EFACTURAaccepted when ANAF's state is okThe ANAF upload index.rejected when the state is nok, with ANAF's error code. The upload follows ANAF's documentation and has not been tried; only its validators have run.
PEPPOLdeliveredThe access point's document id.rejected when the access point refuses it or reports a failure.
FR-PAdelivered, then buyer_status eventsThe platform's invoice id. The French code, its label and any note travel in route.raw.rejected when the platform refuses it, for example fr:213.
DE-XRECHNUNGNo authority answers. The built and checked file is the result.Delivery follows the channel, Peppol or email.The 422 at intake. No rail answer follows.
  • Transient rail errors never become events. They retry (see limits).
  • A French status code the service does not map gives no event and raises an alert, so it is not dropped.
  • A buyer a rail cannot reach. For Peppol, the service checks the scheme code of the buyer's id, not whether the buyer is registered. An access point may report a buyer that is not on Peppol as not reachable, and the mapping turns that into rejected with EI-PEPPOL-NO-ROUTE. That follows the access point's documentation and has not been confirmed on a live access point. A French buyer without a platform address should fail, not deliver; that has not been confirmed either.

On this page