Skip to main content

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:

  1. Open Postman
  2. Click Import โ†’ Link
  3. Enter: https://docs.goroute.ai/openapi/goroute-api.json
  4. 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:

VariableValue
base_urlhttps://app.goroute.ai/peppol-api
api_keyyour-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:

FolderOperations
Compass27
Drafts20
Invoice Intelligence18
Transactions18
Connectors18
Public16
Settings12
Approval Workflow12
Webhooks11
Import Jobs11

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_type is the name of the XML root element โ€” Invoice or CreditNote โ€” not the long document type identifier you send in a request.
  • profile is echoed straight back from your request. Send no profile and you get null back; 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:

VariableDescriptionExample
{{$timestamp}}Current Unix timestamp1706284800
{{$randomUUID}}Random UUIDa1b2c3d4-e5f6-...
{{$isoTimestamp}}ISO 8601 date2026-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โ€‹

  1. Send Document โ€” POST to /api/v1/documents
  2. Save Transaction ID โ€” store transaction_id from the 202 response
  3. Poll Status โ€” GET /api/v1/transactions/{transaction_id}
  4. 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:

  1. Create a webhook.site URL
  2. Register it as a webhook endpoint
  3. Send a document
  4. Watch the webhook arrive in real-time

Common Issuesโ€‹

401 Unauthorizedโ€‹

Problem: API key is missing or invalid

Solution:

  • Check that api_key environment 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 document field
  • 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.

Corrected on 19 September 2026

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.

Corrected on 21 September 2026 โ€” every worked example on this page used to fail

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.