Postman Collection
Our Postman collection lets you explore and test the GoRoute API interactively. It includes all endpoints with pre-configured examples, making it easy to understand the API before writing code.
Quick Startโ
1. Import the Collectionโ
Import the published OpenAPI description โ Postman builds the whole collection from it, and it is generated from the running service, so it never drifts:
- Open Postman
- Click Import โ Link
- Enter:
https://docs.goroute.ai/openapi/goroute-api.json - Click Import
That URL is the same description this site's API Reference is built from.
2. Configure Environmentโ
Create a new environment with the following variables:
| Variable | Value |
|---|---|
base_url | https://app.goroute.ai/peppol-api |
api_key | your-api-key-here |
3. Set Up Authenticationโ
The collection uses a pre-request script to automatically add the API key header:
pm.request.headers.add({
key: 'X-API-Key',
value: pm.environment.get('api_key')
});
What the import gives youโ
Postman does not read a folder layout we maintain by hand. It builds the collection from the description you imported, so what you see is whatever the API publishes on the day you import it.
Measured on 21 September 2026, the published description held 277 paths and 324 operations, and Postman grouped them into 42 folders โ one folder per tag in the description. The biggest folders were:
| Folder | Operations |
|---|---|
| Compass | 27 |
| Drafts | 20 |
| Invoice Intelligence | 18 |
| Transactions | 18 |
| Connectors | 18 |
| Public | 16 |
| Settings | 12 |
| Approval Workflow | 12 |
| Webhooks | 11 |
| Import Jobs | 11 |
Two things surprise people. The Documents folder is small โ it holds exactly two
operations, POST /api/v1/documents and POST /api/v1/documents/validate โ because
sending is one call, not a family of them. And the three requests in the Health folder
are addressed off the root of the host rather than under /api/v1: GET {{base_url}}/health, GET {{base_url}}/health/ready and GET {{base_url}}/health/live.
They answer without an API key, so they are the quickest way to confirm your base_url is
right before you start debugging anything else.
Those counts are a measurement on a given day, not a promise. Re-import and the shape follows whatever the API publishes then.
Example Requestsโ
Every address below begins with /api/v1. With the base_url from
Configure Environment that makes the full address
https://app.goroute.ai/peppol-api/api/v1/โฆ. Leaving /api/v1 out does not reach a
different version of the API โ it reaches nothing at all.
Send an Invoiceโ
You do not post raw XML. The request is JSON, and your UBL invoice travels as a string in
the document field.
POST {{base_url}}/api/v1/documents
X-API-Key: {{api_key}}
Content-Type: application/json
{
"receiver_scheme": "9959",
"receiver_id": "987654321",
"document": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Invoice xmlns=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\">...</Invoice>"
}
receiver_scheme, receiver_id and document are the only required fields. Everything
else โ the sender, the document type, the process identifier โ falls back to a sensible
default, which for the sender is your organisation's registered participant.
Response โ 202 Accepted:
{
"transaction_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"message": "Document queued for delivery",
"created_at": "2026-09-21T10:30:00Z",
"idempotency_key": null
}
status is queued here, not delivered. The call returns as soon as the document is
accepted onto the queue; delivery happens afterwards, and you find out how it went from the
transaction or from a webhook.
Sending an Invoice covers the optional fields, the
idempotency header, and how to track what happens after the 202.
Lookup a Participantโ
GET {{base_url}}/api/v1/participants/lookup?peppol_id=0088:1234567890123
X-API-Key: {{api_key}}
peppol_id is the preferred query parameter; identifier is accepted as well and means the
same thing.
Response:
{
"found": true,
"participant_id": "0088:1234567890123",
"name": "Example Trading B.V.",
"country": "NL",
"capabilities": [
"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice"
],
"message": null
}
Only found and participant_id are always present. The rest may be null or empty
depending on what the registry returned.
Validate Documentโ
POST {{base_url}}/api/v1/documents/validate
X-API-Key: {{api_key}}
Content-Type: application/json
{
"document": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Invoice ...>...</Invoice>"
}
Errors and warnings come back in one issues list, each entry carrying its own
severity. There is no separate errors array and no separate warnings array.
Response โ a document that passed:
{
"valid": true,
"document_type": "Invoice",
"profile": null,
"error_count": 0,
"warning_count": 1,
"issues": [
{
"severity": "warning",
"code": "BR-CO-26",
"message": "Either BuyerReference or OrderReference should be present",
"location": "/Invoice",
"rule_id": null
}
],
"sender_id": "0106:12345678",
"receiver_id": "0088:1234567890123",
"document_id": "INV-2026-001",
"issue_date": "2026-09-21"
}
Response โ a document that failed:
{
"valid": false,
"document_type": "Invoice",
"profile": null,
"error_count": 1,
"warning_count": 0,
"issues": [
{
"severity": "error",
"code": "BR-21",
"message": "At least one InvoiceLine is mandatory",
"location": "/Invoice/cac:InvoiceLine",
"rule_id": null
}
],
"sender_id": null,
"receiver_id": null,
"document_id": null,
"issue_date": null
}
Two fields catch people out:
document_typeis the name of the XML root element โInvoiceorCreditNoteโ not the long document type identifier you send in a request.profileis echoed straight back from your request. Send noprofileand you getnullback; it is not something the service works out for you.
To decide pass or fail in a test script, read valid or error_count.
Using Collection Variablesโ
The collection supports dynamic variables for testing:
| Variable | Description | Example |
|---|---|---|
{{$timestamp}} | Current Unix timestamp | 1706284800 |
{{$randomUUID}} | Random UUID | a1b2c3d4-e5f6-... |
{{$isoTimestamp}} | ISO 8601 date | 2026-01-26T10:30:00Z |
Example with Variablesโ
The send request has no document_id, correlation_id or issued_date field. Anything of
your own that you want stored alongside the transaction goes in metadata, and the
Idempotency-Key header is how you stop a retry from sending twice.
POST {{base_url}}/api/v1/documents
X-API-Key: {{api_key}}
Content-Type: application/json
Idempotency-Key: postman-{{$randomUUID}}
{
"receiver_scheme": "9959",
"receiver_id": "987654321",
"document": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Invoice ...>...</Invoice>",
"metadata": {
"our_reference": "INV-{{$timestamp}}",
"sent_from": "postman"
}
}
Testing Workflowsโ
Complete Send โ Track โ Verify Flowโ
- Send Document โ POST to
/api/v1/documents - Save Transaction ID โ store
transaction_idfrom the202response - Poll Status โ GET
/api/v1/transactions/{transaction_id} - Verify Delivery โ check for
status: delivered
// Test script to save transaction ID
if (pm.response.code === 202) {
const response = pm.response.json();
pm.environment.set('last_transaction_id', response.transaction_id);
}
Webhook Testingโ
Use Postman's mock servers or services like webhook.site to test webhook delivery:
- Create a webhook.site URL
- Register it as a webhook endpoint
- Send a document
- Watch the webhook arrive in real-time
Common Issuesโ
401 Unauthorizedโ
Problem: API key is missing or invalid
Solution:
- Check that
api_keyenvironment variable is set - Verify the key hasn't expired
- Ensure no extra whitespace in the key
400 Bad Requestโ
Problem: Invalid request format
Solution:
- Validate your JSON syntax, and the UBL XML inside the
documentfield - Send
Content-Type: application/jsonโ the API does not accept raw XML bodies - Use the validation endpoint first
404 Not Found, or 405 Method Not Allowedโ
Problem: Most often the address is missing /api/v1, so nothing is listening at it. A
405 on a POST and a 404 on a GET are what this API answers for an address that does not
exist at all โ the same answer an invented address gets.
Solution:
- Check the address begins
{{base_url}}/api/v1/โฆ - Check the participant identifier format
- Check the transaction ID is correct, and that it was created against the same environment
Where the collection comes fromโ
There is no collection file to download, and no environment file either. You build the collection in Postman by importing one address:
https://docs.goroute.ai/openapi/goroute-api.json
That is the description this site's API Reference is generated from โ an OpenAPI 3.1 document in JSON, covering the 277 documented paths of the GoRoute API. Postman builds every folder, request and example from it, which is why it cannot fall behind a hand-maintained file. See Import the Collection above for the four steps.
The two environment variables to create yourself are in Configure Environment.
This page used to offer three downloads here: a Postman collection, an environment template,
and the API service's own OpenAPI description at
https://app.goroute.ai/peppol-api/openapi.json. All three answered 404 when we checked
them on 19 September 2026, so they have been replaced by the import instruction above, which
was already at the top of this page and works.
If you built requests by hand from this page before 21 September 2026, they did not work, and the fault was ours. Here is what was wrong, so you can tell which of your requests to throw away.
The send address did not exist. The page said POST {{base_url}}/documents/send. There
has never been a documents/send path on this API. The address is
POST {{base_url}}/api/v1/documents.
The other addresses were missing /api/v1. Lookup and validate were written as
{{base_url}}/participants/lookup and {{base_url}}/documents/validate. Neither reaches
anything. Both need /api/v1 in front.
The send request was the wrong content type. The page showed raw UBL XML posted as
application/xml. The request is application/json, and the XML goes in the document
field of the JSON body, alongside receiver_scheme and receiver_id.
Three response examples showed fields that do not exist. The lookup example listed
registered, document_types and endpoint_url; the real fields are found,
participant_id, name, country, capabilities and message. The validate examples
split results into errors and warnings arrays; the real response has a single issues
list. The "Example with Variables" body used document_id, correlation_id and
issued_date, none of which the send request accepts.
The collection diagram was wrong about the size of the API. It drew 5 folders and 13 requests. The import actually produced 42 folders and 324 operations when we measured it on 21 September 2026.
Two other pages already carried the correction for the documents/send address โ
Create a Sender and
Sending an Invoice โ and this page was missed. It has
now been checked against the published API description line by line.