Skip to main content

Counting and listing sent documents

Two calls answer the questions a dashboard asks. One counts your documents over a period. The other lists the documents you sent, page by page, and can attach the invoice you originally submitted.

All paths below are relative to https://app.goroute.ai/peppol-api. Both calls need the transactions:read permission and read only your own organisation, unless you ask for the whole group with scope=group.

Method and pathWhat it does
GET /api/v1/transactions/statsCounts by direction and by status over a date range
GET /api/v1/transactions/historyYour sent documents, paged, optionally with the original invoice
/history is sent documents only

The name does not say so, but the endpoint fixes the direction to sent and there is no parameter to change it. Received documents never appear in its results. To read what you received, use GET /api/v1/inbound-documents or GET /api/v1/transactions without a direction filter.

Count documents by statusโ€‹

GET /api/v1/transactions/stats

ParameterTypeWhat it does
date_fromdate-timeStart of the period. Defaults to 30 days before date_to
date_todate-timeEnd of the period. Defaults to now
exclude_reporting_legsboolean, default falseLeaves out the extra copies GoRoute sends to a tax authority, so the counts match the documents you recognise
scopestringgroup counts the caller's organisation and every active entity beneath it, at any depth. Any other value, or none, counts your own organisation only
curl -H "X-API-Key: your_api_key" \
"https://app.goroute.ai/peppol-api/api/v1/transactions/stats?date_from=2026-08-01T00:00:00&date_to=2026-08-31T23:59:59&exclude_reporting_legs=true"
{
"total": 0,
"sent": 0,
"received": 0,
"delivered": 0,
"failed": 0,
"pending": 0,
"period_start": "2026-08-01T00:00:00Z",
"period_end": "2026-08-31T23:59:59Z",
"by_entity": null
}

Reading the numbersโ€‹

period_start and period_end are the window actually used, so you can see what the defaults resolved to.

The six counts are two different cuts of the same documents, not one list of six parts:

  • sent and received split the documents by direction. Together they make total.
  • delivered, failed and pending count by status. pending means queued, submitted, accepted or retrying.

So sent + received equals total, but delivered + failed + pending usually does not. Two more statuses exist and sit in none of the three buckets: held, a document prepared and deliberately not yet transmitted because the tax authority's endpoint is not live, and issued, a document delivered to the buyer by email as a PDF/A-3 hybrid because they are not on the network. Neither is a failure and neither is counted as one.

One document type is counted in a way worth knowing: an Oman export reported under the substitute participant is stored as failed but counts as delivered here, because nothing about it is outstanding. The same rule is applied by the status filter on GET /api/v1/transactions, so the counts and the rows agree.

Soft-deleted documents are left out of every count.

Group totalsโ€‹

With scope=group, the six counts cover the whole subtree and by_entity fills in โ€” one row per entity that has at least one matching document, sorted by name:

{
"by_entity": [
{
"org_id": "3f2b9c10-6d44-4c1e-9a8a-5b7e3f0a1d22",
"name": "Nordlys Retail AS",
"sent": 0,
"received": 0,
"delivered": 0,
"failed": 0,
"total": 0
}
]
}

Outside group scope by_entity is null. scope=group is refused with 400 and NOT_A_GROUP when nothing sits beneath you or you are acting as another organisation read-only, and with 400 and GROUP_VIEW_DISABLED where the operator has switched the group view off.

List sent documentsโ€‹

GET /api/v1/transactions/history

ParameterTypeWhat it does
pageinteger, default 1Which page to return
page_sizeinteger, default 20, maximum 100Rows per page
statusstringReturn only documents with this status
date_from, date_todate-timeRestrict to documents created in this window
document_numberstringRead the caveat below before using this
include_invoice_databoolean, default falseAttach the invoice as originally submitted to each row
scopestringgroup reads the same series across the caller's whole subtree. Rows keep their shape; there is no per-entity split
curl -H "X-API-Key: your_api_key" \
"https://app.goroute.ai/peppol-api/api/v1/transactions/history?page=1&page_size=50&status=failed"
{
"items": [
{
"transaction_id": "7c1f7d54-2a3f-4a51-9a2f-1c9d0a6b5e21",
"status": "failed",
"document_number": "INV-2026-000417",
"receiver_peppol_id": "0192:910000047",
"created_at": "2026-08-14T09:12:44Z",
"has_invoice_data": true,
"can_resend": true,
"invoice_data": null
}
],
"total": 0,
"page": 1,
"page_size": 50,
"total_pages": 0
}

has_invoice_data says whether the original invoice was kept for that document. can_resend is true only when the document failed or is retrying and the original invoice is still there โ€” the two conditions for POST /api/v1/transactions/{transaction_id}/resend to have anything to send. invoice_data stays null until you ask for it with include_invoice_data=true.

document_number filters one page, not the whole history

GoRoute fetches the page first and then keeps the rows on that page whose document number contains what you asked for. Two things follow, and neither is reported in the response:

  1. A page can come back with fewer rows than page_size โ€” sometimes none at all โ€” while total and total_pages still describe the unfiltered series.
  2. A matching document that sits on another page is never found.

To search reliably, use GET /api/v1/transactions, whose invoice_number filter is applied to the whole series before paging. Note the difference in behaviour as well as in reliability: invoice_number there is an exact match, because an invoice number is an identifier and a partial match would hand back the wrong document; document_number here matches any row containing the text.

/history has no exclude_reporting_legs parameter, so reporting legs are included in its rows and in its total. If you are comparing counts with rows, compare GET /api/v1/transactions/stats against GET /api/v1/transactions with the same exclude_reporting_legs value, not against this endpoint.