Skip to main content

Client Libraries

GoRoute does not publish client libraries

There is no official GoRoute SDK for Python, Node.js, C#, Java or any other language. Nothing is available to install from PyPI, npm, NuGet or Maven Central.

Earlier revisions of this page listed four "official" SDKs with installation commands, quick-start code and repository links. None of those packages has ever been published, and none of those repositories exists. Code written against them has never worked.

If you copied an install command from this pageโ€‹

Until this revision, this page printed package names for PyPI, npm, NuGet and Maven Central that GoRoute does not own or control, and linked to source repositories that return 404.

Please treat that as a supply-chain matter rather than a typo:

  • Those names are unregistered. An unregistered name in a published install instruction is a dependency-confusion opportunity โ€” today the install simply fails, but whoever registers the name first can have their code run inside your build.
  • Remove them from your dependency manifests (requirements.txt, pyproject.toml, package.json, .csproj, pom.xml, build.gradle) and from any lockfile, then re-resolve.
  • If one of those names ever does resolve for you, do not trust it. It is not ours.

The names are deliberately not repeated on this page, so that they cannot be copied out of it again. To find what to remove, look for a dependency naming GoRoute or Peppol that you cannot trace back to a first-party source.

What to use insteadโ€‹

The GoRoute Peppol API is plain HTTPS + JSON. There is no SDK to learn: authentication is a single header, and sending a document is one POST with a JSON body. A working client is a few lines in any language that can make an HTTP request.

The one endpoint most integrations needโ€‹

Method and pathPOST /api/v1/documents
Base URLhttps://app.goroute.ai/peppol-api
Full URLhttps://app.goroute.ai/peppol-api/api/v1/documents
Auth headerX-API-Key: your_api_key
Content typeapplication/json
Optional headerIdempotency-Key โ€” prevents duplicate sends on retry
Success status202 Accepted (queued for asynchronous delivery)

Request body:

FieldRequiredNotes
receiver_schemeYesReceiver Peppol scheme, e.g. 9959
receiver_idYesReceiver Peppol identifier
documentYesThe UBL document as an XML string inside the JSON body โ€” you do not POST raw XML
sender_schemeNoDefaults to your organization's participant
sender_idNoDefaults to your organization's participant
metadataNoFree-form object stored with the transaction

A successful response returns transaction_id, status and created_at. Track delivery with webhooks or by polling the transaction.

For the complete send workflow, including the UBL document itself, see Sending an Invoice.

Pythonโ€‹

Using requests:

import requests

with open("invoice.xml", "r", encoding="utf-8") as f:
invoice_xml = f.read()

response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/documents",
headers={
"X-API-Key": "your_api_key",
"Content-Type": "application/json",
# Optional: makes the send safe to retry
"Idempotency-Key": "invoice-2026-00123",
},
json={
"receiver_scheme": "9959",
"receiver_id": "987654321",
"document": invoice_xml,
},
timeout=30,
)

response.raise_for_status() # 202 on success
result = response.json()
print(result["transaction_id"], result["status"])

For async applications the same call with httpx.AsyncClient or aiohttp works identically โ€” there is nothing GoRoute-specific about it.

Node.js / TypeScriptโ€‹

Using the built-in fetch (Node 18+):

import { readFile } from 'node:fs/promises';

const invoiceXml = await readFile('invoice.xml', 'utf8');

const response = await fetch(
'https://app.goroute.ai/peppol-api/api/v1/documents',
{
method: 'POST',
headers: {
'X-API-Key': process.env.GOROUTE_API_KEY,
'Content-Type': 'application/json',
// Optional: makes the send safe to retry
'Idempotency-Key': 'invoice-2026-00123',
},
body: JSON.stringify({
receiver_scheme: '9959',
receiver_id: '987654321',
document: invoiceXml,
}),
},
);

if (!response.ok) {
throw new Error(`Send failed: ${response.status} ${await response.text()}`);
}

const result = await response.json(); // 202 Accepted
console.log(result.transaction_id, result.status);

C# / .NETโ€‹

Using HttpClient:

using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;

var invoiceXml = await File.ReadAllTextAsync("invoice.xml");

using var http = new HttpClient
{
BaseAddress = new Uri("https://app.goroute.ai/peppol-api/")
};
http.DefaultRequestHeaders.Add(
"X-API-Key", Environment.GetEnvironmentVariable("GOROUTE_API_KEY"));

using var request = new HttpRequestMessage(HttpMethod.Post, "api/v1/documents")
{
Content = JsonContent.Create(new
{
receiver_scheme = "9959",
receiver_id = "987654321",
document = invoiceXml
})
};
// Optional: makes the send safe to retry
request.Headers.Add("Idempotency-Key", "invoice-2026-00123");

var response = await http.SendAsync(request);
response.EnsureSuccessStatusCode(); // 202 on success

using var payload = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
Console.WriteLine(payload.RootElement.GetProperty("transaction_id").GetString());

Register the HttpClient with IHttpClientFactory and add your own Polly retry policy in the usual way โ€” none of that is GoRoute-specific.

Javaโ€‹

Using java.net.http.HttpClient (Java 11+):

import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;

String invoiceXml = Files.readString(Path.of("invoice.xml"));

String body = new ObjectMapper().writeValueAsString(Map.of(
"receiver_scheme", "9959",
"receiver_id", "987654321",
"document", invoiceXml
));

HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.goroute.ai/peppol-api/api/v1/documents"))
.header("X-API-Key", System.getenv("GOROUTE_API_KEY"))
.header("Content-Type", "application/json")
// Optional: makes the send safe to retry
.header("Idempotency-Key", "invoice-2026-00123")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();

HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println(response.statusCode()); // 202 on success
System.out.println(response.body());

Generating a client from the OpenAPI documentโ€‹

You can point OpenAPI Generator or a similar tool at our published specification โ€” see the Code Generation guide.

A generated client will not cover the API

The published OpenAPI document describes 8 paths. The live API exposes several hundred. A client generated from it will therefore cover a small fraction of the product, and the absence of a method in a generated client tells you nothing about whether the endpoint exists.

Generate a client for the endpoints the specification actually contains, and write the rest by hand against this documentation.

Webhooksโ€‹

Webhook payloads are not covered on this page. Earlier revisions carried a webhook handler sample here that used the wrong envelope field and two event names that do not exist in the product.

The canonical references are:

Getting Helpโ€‹