Invoice status
Every status code an invoice can carry, and the endpoints for reading one invoice's current state. The full list is published below and served by an unauthenticated endpoint, so a code you have not seen before never has to reach your users as an unrecognised state.
An invoice carries a status trail — an append-only array of { code, message, created_at } rows. Rows are never replaced, so the last row is the invoice's current state. Every code below can appear in that array; nothing outside this list is emitted.
Rather than matching on codes directly, switch on category and stop polling when terminal is true — the status endpoint returns both, so a new code added to a phase you already handle needs no change on your side. A code your integration does not recognise comes back as category: "unknown", never as a missing field.
Work is still in flight. Keep polling; a further status row is expected.
The step completed successfully.
The step failed. See the row's message (and errors, when present).
Nothing is wrong with the document - it is parked waiting on configuration or a human decision, and will move on once that is resolved.
Poll one invoice
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
https://api.taxstar.app/einv/oauth/invoices/{invoice_id}/status
{
"invoice_id": "68f0aabbccddeeff00112233",
"invoice_number": "INV-1042",
"direction": "sent",
"status": "VALIDATION_FAILED",
"message": "Validation failed: 2 rules failed",
"created_at": "2026-09-11T08:14:02.911+00:00",
"category": "failed",
"phase": "validation",
"terminal": true,
"description": "The invoice failed validation and was not sent. ...",
"final_status": "failed",
"status_count": 3,
"errors": [{ "rule": "ibr-173-ae", "message": "..." }]
}44 codes · catalogue v1.0.0
Queued
PROCESSINGin progress | The invoice was accepted and queued for processing. This is the status returned by POST /oauth/invoices and by a PATCH that re-queues an invoice. | sent · received |
WEBHOOK_RECEIVEDin progress | The processing pipeline picked the queued invoice up and started work on it. | sent · received |
Validation
VALIDATION_IN_PROGRESSin progress | The invoice is being checked against the PINT AE rules. | sent · received |
VALIDATION_SUCCEEDEDsuccess | The invoice passed validation and moves on to XML conversion. | sent · received |
VALIDATION_FAILEDfailedterminal | The invoice failed validation and was not sent. The status row carries an 'errors' array with the failing rules. Fix the data and PATCH the invoice to re-queue it. Run POST /oauth/invoices/validate first to see the same errors without creating an invoice. | sent · received |
XML conversion
XML_CONVERTEDsuccess | The invoice was converted to UBL XML, ready for dispatch. | sent |
XML_CONVERTED_FAILEDfailedterminal | UBL XML could not be produced from the invoice data. Fix the data and PATCH the invoice to re-queue it. | sent |
XML_VALIDATEDsuccess | The generated UBL XML passed schema validation. | sent |
XML_VALIDATED_FAILEDfailedterminal | The generated UBL XML failed schema validation. | sent |
Dispatch to Peppol
SENT_TO_PEPPOLsuccessterminal | The invoice was accepted by the Peppol access point for delivery. This is the terminal success state of the send flow: the invoice becomes immutable and a PATCH returns 409. | sent · received |
SENT_TO_PEPPOL_FAILEDfailedterminal | The access point rejected the invoice at dispatch. The invoice is still editable - PATCH it to re-queue. | sent · received |
SENT_TO_BILLBERRYsuccessterminallegacy | Legacy spelling of SENT_TO_PEPPOL, written before the gateway was renamed. Treat it exactly as SENT_TO_PEPPOL. Treat as SENT_TO_PEPPOL. | sent · received |
SENT_TO_BILLBERRY_FAILEDfailedterminallegacy | Legacy spelling of SENT_TO_PEPPOL_FAILED. Treat it exactly as SENT_TO_PEPPOL_FAILED. Treat as SENT_TO_PEPPOL_FAILED. | sent · received |
Peppol delivery
DELIVERED_BY_PEPPOLsuccessterminalreserved | The receiving access point acknowledged the document. Reported asynchronously after SENT_TO_PEPPOL. Published ahead of its producer - recognise it now, do not expect it yet. | sent |
PEPPOL_DELIVERY_FAILEDfailedterminalreserved | The receiving access point rejected the document after it had been accepted for delivery. Published ahead of its producer - recognise it now, do not expect it yet. | sent |
Arrival
RECEIVED_BY_PEPPOLin progress | An invoice addressed to one of your entities arrived over the Peppol network and was stored. This is the first row on every received invoice. | received |
RECEIVED_BY_BILLBERRYin progresslegacy | Legacy spelling of RECEIVED_BY_PEPPOL. Treat it exactly as RECEIVED_BY_PEPPOL. Treat as RECEIVED_BY_PEPPOL. | received |
Routing
WAITING_FOR_ERP_CONNECTIONblocked | The invoice was received for one of your entities, but that entity has no connected ERP to route it into. It is held and delivered once an ERP is connected. | received |
WAITING_FOR_TAX_CONFIGURATIONblocked | The invoice is compliant, but its VAT treatment has no matching tax code in the receiving entity's ERP profile. Held until the tax code is configured - the document itself needs no change. | received |
WAITING_FOR_APPROVALblocked | The invoice is waiting for a human approval decision before it is pushed into the ERP. | received |
INVOICE_OPERATION_DISABLEDblockedterminal | Invoice operations are switched off for the entity, so the invoice was deliberately not processed. Neither a success nor a failure. | sent · received |
DATA_MISSINGfailedterminal | The received document is missing data required to route it into an ERP. | received |
DRAFT_BLOCKEDfailedterminal | The invoice was left as a draft and not processed further. | received |
APPROVEDsuccess | A received invoice was approved and continues into the ERP. | received |
REJECTEDfailedterminal | A received invoice was rejected by the recipient. | received |
Delivery into your ERP
SENT_TO_XERO_IN_PROGRESSin progress | The received invoice is being pushed into Xero. | received |
SENT_TO_XEROsuccessterminal | The received invoice was delivered into Xero. | received |
SENT_TO_XERO_FAILEDfailedterminal | The received invoice could not be delivered into Xero; the row's message carries the ERP's error. | received |
SENT_TO_QUICKBOOKS_IN_PROGRESSin progress | The received invoice is being pushed into QuickBooks. | received |
SENT_TO_QUICKBOOKSsuccessterminal | The received invoice was delivered into QuickBooks. | received |
SENT_TO_QUICKBOOKS_FAILEDfailedterminal | The received invoice could not be delivered into QuickBooks; the row's message carries the ERP's error. | received |
SENT_TO_ZOHO_IN_PROGRESSin progress | The received invoice is being pushed into Zoho. | received |
SENT_TO_ZOHOsuccessterminal | The received invoice was delivered into Zoho. | received |
SENT_TO_ZOHO_FAILEDfailedterminal | The received invoice could not be delivered into Zoho; the row's message carries the ERP's error. | received |
SENT_TO_NAQOOD_IN_PROGRESSin progress | The received invoice is being pushed into Naqood. | received |
SENT_TO_NAQOODsuccessterminal | The received invoice was delivered into Naqood. | received |
SENT_TO_NAQOOD_FAILEDfailedterminal | The received invoice could not be delivered into Naqood; the row's message carries the ERP's error. | received |
SENT_TO_ODOO_IN_PROGRESSin progress | The received invoice is being pushed into Odoo. | received |
SENT_TO_ODOOsuccessterminal | The received invoice was delivered into Odoo. | received |
SENT_TO_ODOO_FAILEDfailedterminal | The received invoice could not be delivered into Odoo; the row's message carries the ERP's error. | received |
SENT_TO_WAFEQ_IN_PROGRESSin progress | The received invoice is being pushed into Wafeq. | received |
SENT_TO_WAFEQsuccessterminal | The received invoice was delivered into Wafeq. | received |
SENT_TO_WAFEQ_FAILEDfailedterminal | The received invoice could not be delivered into Wafeq; the row's message carries the ERP's error. | received |
/oauth/invoices/{invoice_id}/statusAccess tokenGet current status (sent)
Return ONLY the current status of a sent invoice — the last row of its status trail, plus how that code should be treated. `status` is the raw code; `category` collapses it into in_progress / success / failed / blocked so you do not have to hard-code which codes mean what; `terminal` tells you when to stop polling. A VALIDATION_FAILED response also carries the failing rules in `errors`.
Use this, not the full invoice endpoint, to follow an invoice. It projects away the invoice data and the status history, so it stays cheap to poll. Stop when the response has terminal: true.
Path parameters
invoice_id | Invoice id returned by POST /oauth/invoices (also accepted at /oauth/invoices/sent/{invoice_id}/status). |
/oauth/invoices/received/{invoice_id}/statusAccess tokenGet current status (received)
Return ONLY the current status of a received invoice, in the same shape as the sent-invoice status endpoint.
Path parameters
invoice_id | Billberry invoice id (the `id` field from the received-invoices list). |
/oauth/invoices/status-codesPublicList all status codes
The complete published catalogue of invoice status codes, machine-readable. Each entry carries `code`, `phase`, `category`, `terminal`, `applies_to` and a description; `deprecated` entries are legacy wire values still present on historical documents (with `superseded_by` naming the current code), and `reserved` entries are published ahead of their producer. No authentication required — cache the response and compare `version` to detect a change.
Query parameters
direction | Restrict to codes that appear on `sent` or on `received` invoices. Defaults to all. |