Skip to main content

SMP Registration

The Service Metadata Publisher (SMP) is the directory that tells the Peppol network where to find you. When you register in the SMP, other participants can discover your capabilities and send you documents.

You do not need the API for this

SMP registration is fully self-serve in the browser: the registration wizard walks through business details, participants, Access Point choice (GoRoute's AP, your own, or another provider's) and document types, and the SMP Dashboard shows live network status, the published business card and document types, certificate expiry, and provides register / deregister / delete with confirmation dialogs. The API below is the machine equivalent of the same flow.

What is SMP?โ€‹

The SMP stores:

  1. Who you are โ€” Your Peppol identifier
  2. What you can receive โ€” Document types and processes
  3. How to reach you โ€” Your Access Point's endpoint
  4. Security info โ€” Certificates for message encryption
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ SMP Record โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Participant: 0106:12345678 โ”‚
โ”‚ โ”œโ”€โ”€ Document: Invoice-2 โ”‚
โ”‚ โ”‚ โ””โ”€โ”€ Process: BIS Billing 3.0 โ”‚
โ”‚ โ”‚ โ””โ”€โ”€ Endpoint: https://ap.goroute.ai/as4 โ”‚
โ”‚ โ””โ”€โ”€ Document: CreditNote-2 โ”‚
โ”‚ โ””โ”€โ”€ Process: BIS Billing 3.0 โ”‚
โ”‚ โ””โ”€โ”€ Endpoint: https://ap.goroute.ai/as4 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

How SMP Lookup Worksโ€‹

When GoRoute sends an invoice to a receiver:

1. Sender provides: 0106:12345678 (receiver ID)
โ”‚
โ–ผ
2. GoRoute queries SML: Where is this participant's SMP?
โ”‚
โ–ผ
3. SML returns: smp-goroute.acc.edelivery.tech (SMP URL)
โ”‚
โ–ผ
4. GoRoute queries SMP: What are this participant's capabilities?
โ”‚
โ–ผ
5. SMP returns:
- Document types: Invoice, Credit Note
- Access Point: https://receiver-ap.example.com/as4
- Certificate: [X.509 certificate]
โ”‚
โ–ผ
6. GoRoute delivers invoice to receiver's Access Point

Registration Processโ€‹

Step 1: Create Participantโ€‹

First, create a participant record in GoRoute:

import requests

participant = {
"scheme": "0106",
"identifier": "12345678",
"name": "My Company BV",
"country": "NL",
"email": "invoices@mycompany.nl"
}

response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/participants",
headers={
"X-API-Key": "your_api_key",
"Content-Type": "application/json"
},
json=participant
)

result = response.json()
print(f"Participant ID: {result['id']}")

Step 1a: Ask which document types are on offerโ€‹

GET /peppol/doc-types lists the document types GoRoute is willing to publish for a country โ€” the curated set. The doc_type_id values it returns are exactly the values you may put in the optional document_types list in Step 2. If you intend to register with the country defaults and nothing else, you can skip this step.

Two things about this endpoint that catch people out
  • The path has no /api/v1 prefix. It is /peppol/doc-types, appended directly to the base URL. Every other endpoint on this site sits under /api/v1, so the natural guess is to add that prefix here too. Do not: this router sits outside the versioned prefix, and the prefixed path does not exist and returns 404.
  • No API key is needed. This endpoint is public. It returns static configuration: the same information anyone already gets by looking up a registered participant in the SMP. Our machine-readable API description currently marks this path as requiring an API key. That is a mistake in the description, not a requirement of the endpoint, and it is recorded as a defect for engineering.
import requests

response = requests.get(
"https://app.goroute.ai/peppol-api/peppol/doc-types",
params={"country": "AU"}, # no API key
)

for entry in response.json()["doc_types"]:
print("default" if entry["default"] else "opt-in ", entry["label"])

country is optional. Omit it and you get the set that applies to a country with no special profile, which today is the Peppol BIS Billing 3.0 invoice and credit note pair. Australia returns nine entries; here are two of them, taken from a real response:

{
"country": "AU",
"doc_types": [
{
"doc_type_id": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:peppol:pint:billing-1@aunz-1::2.1",
"process_id": "urn:peppol:bis:billing",
"label": "PINT A-NZ โ€” Invoice",
"schemes": ["peppol-doctype-wildcard"],
"default": true
},
{
"doc_type_id": "urn:oasis:names:specification:ubl:schema:xsd:Order-2::Order##urn:fdc:peppol.eu:poacc:trns:order:3::2.1",
"process_id": "urn:fdc:peppol.eu:poacc:bis:ordering:3",
"label": "Peppol BIS Ordering 3.0 โ€” Order",
"schemes": ["busdox-docid-qns"],
"default": false
}
]
}
FieldMeaning
doc_type_idThe Peppol document type identifier. This is the value to send in document_types
process_idThe process identifier GoRoute publishes alongside it. You never send this yourself
labelA readable name, meant for a checklist or a dropdown
schemesThe identifier scheme or schemes this type is published under
defaulttrue if a registration with no body publishes it; false if it must be asked for

One entry here can mean more than one entry in the SMP. The PINT A-NZ types are published twice each โ€” once under the exact identifier and once under the wildcard one โ€” but they appear as a single entry, because choosing a document type always keeps every variant it is published under. You select the document type, not the identifier.

Step 2: Register in SMPโ€‹

POST /api/v1/participants/{participant_id}/register โ€” requires the participants:manage permission.

{participant_id} is a UUID, not a Peppol identifier

The path parameter is the UUID of the GoRoute participant record returned by Step 1 โ€” the id field. It is not the scheme:value Peppol identifier. Passing 0106:12345678 here fails.

Document types: country defaults, or an explicit selection

The request body is optional. With no body (or {}), GoRoute registers the participant's country default set:

  • Australia and New Zealand: PINT A-NZ Invoice and Credit Note, published under the peppol-doctype-wildcard scheme only, each as two entries โ€” the exact id (โ€ฆ@aunz-1::2.1) and the wildcard id (โ€ฆ@aunz-1*::2.1). This is the shape the PINT A-NZ Billing specification requires. Peppol BIS Billing 3.0 is not part of this set โ€” for these two countries it is offered as an opt-in, and only for these two. See Document Capabilities for why one scheme and not two.
  • All other countries: Peppol BIS Billing 3.0 Invoice and Credit Note under busdox-docid-qns, as the default.

Optionally send {"document_types": [...]} with ids from GET /peppol/doc-types?country=XX. A selection can only narrow the country's curated set โ€” it never adds anything that is not on that set, and arbitrary identifiers are never published. Opt-in types exist for Australia and New Zealand: Peppol BIS Billing 3.0, PINT A-NZ Self-Billing, Peppol BIS Ordering 3.0 (Order and Order Response) and Peppol BIS Despatch Advice 3.0.

An explicit selection is the full desired set โ€” document types you leave out are removed from the SMP, which is how "remove a document type" works. A registration with no body only ever adds.

An explicit document_types list deletes what you leave out

Sending a document_types list is not a filter on what gets added. It is a statement of everything the participant should advertise from now on. Any document type currently published for that participant and missing from your list is deleted from the SMP. Senders who relied on it will no longer be able to reach the participant with that document type.

Three consequences worth knowing before you send one:

  • The removal is best-effort and does not fail the call. If a deletion is refused, it is reported back in removed_doc_types with an error status, and the rest of the registration still succeeds. A registration reported as successful can still contain a removal that did not happen โ€” read the field, do not assume.
  • The participant's stored record does not shrink. GoRoute merges newly registered types into the local document_types list rather than replacing it, so removed types remain in document_types and are still counted in total_doc_types. Checking the participant record after a narrowing registration will therefore make it look as though nothing was removed. removed_doc_types in the registration response is the truthful record; the local list is not.
  • A list that matches nothing is refused, with a confusing status. If none of the ids you send exist in that country's curated set, nothing is left to register and the call fails with HTTP 502, error_code: SMP_REGISTRATION_FAILED, and a cause reading "None of the requested document types are available for country XX โ€” nothing to register." The 502 is misleading here โ€” nothing failed on the SMP, the request was simply unusable โ€” but 502 is what the service returns today, so that is what is documented. It is recorded as a defect for engineering.

If you want to add capabilities without any risk of removing one, register with no body and then use the SMP Dashboard's Manage checklist, which shows you the current set before you change it.

Oman participants ignore a document_types selection entirely

Oman registrations go through the tax authority's own SMP, which fixes the document type set itself. GoRoute deliberately drops the selection rather than half-applying it, so an Oman participant sent a narrowing list gets the full Oman set and no error and no warning. Nothing is removed either. If you are managing Oman participants, do not use a selection to try to control what they publish; it will look as though it worked.

import requests

response = requests.post(
f"https://app.goroute.ai/peppol-api/api/v1/participants/{participant_id}/register",
headers={"X-API-Key": "your_api_key"},
)

result = response.json()
print(result["participant"], result["service_group"])
print(result["smp_registered"], result["sml_registered"], result["total_doc_types"])

The response reports what the SMP accepted:

FieldMeaning
participantThe scheme:value Peppol identifier
service_groupcreated, already_exists, or error_<status>
document_typesOne entry per document type, each with doc_type_id, scheme and a status of ok or error_<status>
removed_doc_typesPresent only when you sent an explicit document_types list. One entry per document type deleted from the SMP, each with doc_type and a status of removed or error_<status>
business_cardWhat happened to the participant's Business Card โ€” the record that carries the company name across the network. See Business Card below
smp_registeredTrue only when the ServiceGroup and every document type succeeded
sml_registeredTrue when the ServiceGroup succeeded โ€” PHOSS creates the SML entry alongside it
total_doc_typesCount of document types recorded on the local participant record. This count does not go down after a narrowing registration โ€” see the warning above
sml_registered and smp_registered move independently

A participant whose ServiceGroup was created but whose document types were rejected exists in the SML and resolves to nothing. A sender addressing it receives a 404 and an AS4 TRANSPORT_ERROR. If smp_registered is false, the registration is incomplete even though the participant looks present.

The Business Card, and the "Unknown" nameโ€‹

Routing entries tell the network where to send a document. They do not carry the company's name. That comes from a separate record called the Peppol Business Card, and registration publishes one as its own step.

This is why a participant can be correctly registered, fully reachable, and still appear to everyone else on the network as "Unknown": the routing worked and the name was never published.

The name GoRoute publishes is the participant's legal name, or its display name if no legal name is recorded. Both fields are optional on a participant record, so "we hold no name for this participant" is a real case rather than a theoretical one.

The business_card field in the registration response reports what happened:

ValueMeaning
createdThe Business Card was published. This is the normal result
error_<status>The SMP refused the Business Card and returned that HTTP status
errorThe request could not be made at all
skipped_no_nameRouting was published, but no name is recorded for this participant, so no Business Card was published. Add a legal name or display name and register again
skippedThe main registration entry did not succeed, so the Business Card was not attempted
Participants registered before 28 August 2026 may have no Business Card

Registration only began publishing Business Cards in the release that went live on 28 August 2026. A participant registered before that has no Business Card unless one was created another way, and will show as "Unknown" in Peppol Directory searches and in other participants' lookups. Running the registration call again publishes it โ€” a re-registration of an already-published participant is maintenance, so it is not subject to the billing gate below. Send no body and nothing will be removed.

Publishing the Business Card is best-effort by design. A failure is reported in this field and never undoes an otherwise complete registration, so a participant is never left unreachable because their name could not be published. The trade-off is that you have to read the field: a registration can report success and still have no name on the network.

Because Peppol Directory indexing is asynchronous, a newly published Business Card takes minutes to about an hour to appear in Directory search โ€” see Peppol Directory listing.

Billing gate on fresh publishesโ€‹

In production, registering a participant that is not yet on the network requires the organisation's SMP subscription. Without one the endpoint returns HTTP 402 with error_code: SUBSCRIPTION_REQUIRED and nothing is published. The gate applies only to fresh publishes: re-registering an already-published participant (document-type changes, business-card republish) is maintenance and always works, as do deregistration and deletion โ€” billing never strands a live registration.

The billing surface itself:

EndpointPurpose
GET /api/v1/billing/smpSubscription state for the caller's org, plus whether checkout is available
POST /api/v1/billing/smp/checkout-sessionServer-created Stripe Checkout (USD-fixed); returns a redirect URL. 409 if already subscribed
POST /api/v1/billing/smp/portal-sessionStripe customer portal (cards, invoices, cancellation) for existing subscribers

Stripe is the system of record for payment; GoRoute stores no card data.

Registration errorsโ€‹

Registration returns HTTP 502 with one of these error codes:

error_codeWhen
SMP_REGISTRATION_FAILEDThe PHOSS SMP refused or failed the registration
OMAN_SMP_REGISTRATION_FAILEDAn Oman participant was refused by OTA's SMP wrapper
PARTICIPANT_NOT_FOUNDHTTP 404 โ€” no participant with that UUID in your organisation

The Oman error carries a hint: OTA's SMP verifies with the Fawtara Portal that an accepted ServiceProvider-Taxpayer connection exists before it will register a participant. Accept the taxpayer's connection request on the portal first, then retry within three business days.

Step 3: Verify Registrationโ€‹

GET /api/v1/participants/{participant_id}/smp-status โ€” note the hyphen. smp-status is a single path segment; it is not two segments separated by a slash.

response = requests.get(
f"https://app.goroute.ai/peppol-api/api/v1/participants/{participant_id}/smp-status",
headers={"X-API-Key": "your_api_key"},
)

status = response.json()
print(status["registered"], status["participant"])

For a participant on GoRoute's own PHOSS SMP the response carries registered, participant, the service_group_xml when the participant is present, and the locally recorded local_smp_registered, local_sml_registered and local_document_types.

Oman participants take a different path

An Oman participant does not live in GoRoute's PHOSS SMP, and OTA's wrapper is PUT/DELETE only โ€” there is no read route to query. smp-status returns what GoRoute recorded at registration time (registered, participant, rail: "oman-central-smp", smp_registered, sml_registered, document_types) plus a note saying so. Verify authoritatively via the Fawtara Portal (E-Services > SMP Management), SML DNS resolution, or a public SMP GET.

A failed status check returns HTTP 502 with error_code: SMP_CHECK_FAILED.

SMP Record Structureโ€‹

An SMP record contains:

Service Groupโ€‹

<?xml version="1.0" encoding="UTF-8"?>
<ServiceGroup xmlns="http://busdox.org/serviceMetadata/publishing/1.0/">
<ParticipantIdentifier scheme="iso6523-actorid-upis">0106:12345678</ParticipantIdentifier>
<ServiceMetadataReferenceCollection>
<ServiceMetadataReference
href="https://smp.goroute.ai/0106:12345678/services/urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"/>
</ServiceMetadataReferenceCollection>
</ServiceGroup>

Service Metadataโ€‹

<?xml version="1.0" encoding="UTF-8"?>
<ServiceMetadata xmlns="http://busdox.org/serviceMetadata/publishing/1.0/">
<ServiceInformation>
<ParticipantIdentifier scheme="iso6523-actorid-upis">0106:12345678</ParticipantIdentifier>
<DocumentIdentifier scheme="busdox-docid-qns">
urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1
</DocumentIdentifier>
<ProcessList>
<Process>
<ProcessIdentifier scheme="cenbii-procid-ubl">
urn:fdc:peppol.eu:2017:poacc:billing:01:1.0
</ProcessIdentifier>
<ServiceEndpointList>
<Endpoint transportProfile="peppol-transport-as4-v2_0">
<EndpointURI>https://ap.goroute.ai/as4</EndpointURI>
<RequireBusinessLevelSignature>false</RequireBusinessLevelSignature>
<Certificate>MIIF...</Certificate>
<ServiceDescription>GoRoute Peppol Access Point</ServiceDescription>
<TechnicalContactUrl>https://goroute.ai/#contact</TechnicalContactUrl>
</Endpoint>
</ServiceEndpointList>
</Process>
</ProcessList>
</ServiceInformation>
</ServiceMetadata>

Document Capabilitiesโ€‹

What a participant advertises comes from the curated per-country set, which you can ask for at any time โ€” see Step 1a for the endpoint and its fields.

For Australia and New Zealand the curated set is:

Document typeScheme
defaultPINT A-NZ โ€” Invoicepeppol-doctype-wildcard (exact + * ids)
defaultPINT A-NZ โ€” Credit Notepeppol-doctype-wildcard (exact + * ids)
opt-inPeppol BIS Billing 3.0 โ€” Invoice / Credit Notebusdox-docid-qns
opt-inPINT A-NZ Self-Billing โ€” Invoice / Credit Notepeppol-doctype-wildcard (exact + * ids)
opt-inPeppol BIS Ordering 3.0 โ€” Order / Order Responsebusdox-docid-qns
opt-inPeppol BIS Despatch Advice 3.0busdox-docid-qns

Every other country currently gets Peppol BIS Billing 3.0 Invoice + Credit Note as its default, with no opt-ins.

Why Australia and New Zealand use one identifier scheme, not twoโ€‹

PINT A-NZ is published under peppol-doctype-wildcard only. That is not a GoRoute preference; the specification requires it. OpenPeppol's PINT A-NZ Billing BIS, version 1.1.1, section 5.1.3 "Document type identifier scheme" says:

It is mandatory to follow the Policy for Identifiers. Only the peppol-doctype-wildcard Document Type Identifier scheme is allowed.

โ€” PINT A-NZ Billing BIS, section 5.1.3

Publishing PINT A-NZ under busdox-docid-qns as well would therefore be non-conformant. Each PINT A-NZ document type is published twice, but under the same scheme: once under the exact identifier (โ€ฆ@aunz-1::2.1) and once under the wildcard identifier (โ€ฆ@aunz-1*::2.1). Both are needed โ€” GoRoute's run against the OpenPeppol A-NZ testbed failed one test without the exact entry and a different test without the wildcard one.

Australia and New Zealand are the only two countries treated this way.

Why the opt-in types are off by default

Advertising that you accept Orders, Order Responses or Despatch Advices is a promise that the participant's Access Point will accept those documents and that someone will act on them. Only the participant can make that promise, so GoRoute never makes it for them. Turn them on in the registration wizard's checklist, in the SMP Dashboard's Manage control, or by sending an explicit document_types list.

An older registration may still advertise things this list would not publish now

A registration with no body adds and never removes. So an Australian or New Zealand participant registered before the defaults changed on 28 August 2026 may still be advertising Peppol BIS Billing 3.0 โ€” because it was a default then and nothing has taken it away. Registering again with no body will not remove it.

This is a statement about what the code does. It is not an observation of any particular customer's record. To see what a participant actually advertises today, use GET /api/v1/participants/{participant_id}/smp-status or look the participant up in a public SMP. To change it, send an explicit document_types list โ€” and read the warning about deletion in Step 2 first.

SMP Managementโ€‹

Changing document capabilitiesโ€‹

Re-register with an explicit selection โ€” the registration endpoint doubles as the capability editor:

requests.post(
f"https://app.goroute.ai/peppol-api/api/v1/participants/{participant_id}/register",
headers={"X-API-Key": "your_api_key", "Content-Type": "application/json"},
json={"document_types": [
# ids from GET /peppol/doc-types?country=XX โ€” the FULL desired set
]},
)

The explicit list is reconciled against what the SMP currently publishes: selected types are added or refreshed, de-selected types are deleted from the SMP. In the browser, the SMP Dashboard's Manage control on each registered participant is the same operation as a checklist. If the country itself is wrong, correct country on the participant record first โ€” it decides which curated set applies.

Read the deletion warning in Step 2 before you use this. In short: send the complete set you want, not the changes you want; check removed_doc_types in the response to see what was actually taken off the SMP; and do not check the participant record to confirm a removal, because the stored document_types list does not shrink. Oman participants ignore the selection altogether.

You cannot use this to publish a document type that is not on the country's curated set. The selection narrows what GoRoute offers; it cannot add to it. Arbitrary document type identifiers are never published through this API.

An earlier revision documented a PUT capability route

No such route ever existed, and there is still no per-capability endpoint. The only lever is the registration reconcile described above, and only ids from the curated country set are ever published.

Deregister from SMPโ€‹

POST /api/v1/participants/{participant_id}/deregister โ€” a POST, not a DELETE, and it requires the participants:manage permission.

response = requests.post(
f"https://app.goroute.ai/peppol-api/api/v1/participants/{participant_id}/deregister",
headers={"X-API-Key": "your_api_key"},
)

result = response.json()
print(result["participant"], result["status"])
statusMeaning
deletedThe ServiceGroup was removed
not_foundIt was already gone โ€” the desired end state, so this counts as success
error_<status>The SMP refused; the participant is still published

Deleting the ServiceGroup cascades to all of its ServiceMetadata. On success the local record is kept but marked unregistered, and its document types are cleared.

A refused deregistration does not change local state

If the SMP refuses the delete, GoRoute deliberately leaves the local flags untouched and the call fails with HTTP 502 and error_code: SMP_DEREGISTRATION_FAILED. Recording a removal that did not happen would mean believing a participant was gone while they remained reachable โ€” and Oman requires deregistration within one working day of a connection ending. Re-check with smp-status rather than assuming.

Deregistration

Deregistering from SMP means other participants can no longer send you documents via Peppol. Only do this if you're migrating to another Access Point or leaving the network.

Delete the participant recordโ€‹

DELETE /api/v1/participants/{participant_id} needs the participants:manage permission and answers 204 No Content on success. It soft-deletes: the record disappears from the SMP Dashboard and the wizard, but it is retained so that historical transactions still resolve. A participant id that does not belong to your organisation gets 404.

Deregister first. That is the clean sequence, and it is what the dashboard already does โ€” it offers Delete only for participants that are off the network.

If you delete a participant that is still published on the SMP, GoRoute deregisters it for you before deleting anything. Removing the SMP ServiceGroup takes the SML entry and every published ServiceMetadata with it. An entry that has already gone counts as success.

A refused deregistration cancels the delete

If the SMP will not let go of the participant, the call answers HTTP 502 with error_code: SMP_DEREGISTRATION_FAILED and nothing is deleted. The participant is still published, still visible and still yours. Read a 502 here as "try again, or deregister explicitly first" โ€” never as "probably deleted".

An organisation in delivery-simulation mode skips the deregistration step: there is no live registration to take down, so the record is simply soft-deleted.

Two further consequences of a delete are easy to build the wrong assumption on:

  • Re-creating a deleted identifier brings the old record back. Create a participant with a scheme and identifier this organisation deleted earlier, and GoRoute reactivates the original record โ€” same participant UUID โ€” and updates whichever fields you send.
  • A deleted participant frees its place in your plan allowance. Only active participants that are published on the SMP count towards the identifiers your plan includes.

Peppol Directory listingโ€‹

Registration makes a participant routable immediately โ€” any sender's SMP lookup finds it. The public Peppol Directory (directory.peppol.eu; test participants: test-directory.peppol.eu) is a separate search index: after each registration or business-card change, GoRoute's SMP announces the participant to the Directory, which then fetches the business card and indexes it asynchronously โ€” typically minutes, up to about an hour. A fresh registration that lookups resolve but Directory search does not yet show is normal, not a fault.

Test vs Productionโ€‹

Test SMPโ€‹

SML: acc.edelivery.tech
SMP: smp-test.goroute.ai

Production SMPโ€‹

SML: edelivery.tech
SMP: smp.goroute.ai
Environment Isolation

Test and production are completely separate networks. A participant registered in test cannot receive documents from production, and vice versa.

Troubleshootingโ€‹

Registration Failedโ€‹

Error: "Participant already registered with another AP"

The identifier is already registered with a different Access Point. The previous provider must deregister before GoRoute can register.

# Contact GoRoute support for migration assistance
# admin@goroute.ai

Lookup Returns Nothingโ€‹

Error: "Participant not found in SMP"

  1. Check if registration completed successfully
  2. Verify you're using the correct environment (test/prod)
  3. Wait 5-10 minutes for DNS propagation

Registered but not in the Peppol Directoryโ€‹

See Peppol Directory listing โ€” Directory indexing is asynchronous. If a participant is still missing after a few hours, contact admin@goroute.ai.

Wrong Document Typesโ€‹

Error: "Receiver does not support document type"

The receiver's SMP registration doesn't include the document type you're trying to send.

# Check the receiver's capabilities first. The lookup takes a single
# peppol_id in scheme:value form, not a separate scheme and identifier.
response = requests.get(
"https://app.goroute.ai/peppol-api/api/v1/participants/lookup",
params={"peppol_id": "0106:12345678"},
headers={"X-API-Key": "your_api_key"}
)

capabilities = response.json()["capabilities"]

Best Practicesโ€‹

  1. Register Early โ€” Complete SMP registration before going live
  2. Test First โ€” Always register in test environment before production
  3. Check What Was Registered โ€” With no request body the set comes from the participant's country, so confirm it with smp-status rather than assuming. If you sent a document_types selection, also read removed_doc_types in the response: it is the only reliable record of what was taken off the SMP
  4. Send No Body Unless You Mean To Remove Something โ€” A registration with no body only ever adds. A document_types list deletes every published type you leave out
  5. Check the Name, Not Just the Routing โ€” A business_card of skipped_no_name means the participant is reachable but will show as "Unknown" to everyone else on the network
  6. Monitor Status โ€” Set up alerts for SMP registration changes
  7. Keep Records โ€” Maintain history of registration changes

API Referenceโ€‹

All paths are relative to https://app.goroute.ai/peppol-api. {participant_id} is the UUID of the GoRoute participant record in every case.

MethodPathPermissionNotes
GET/peppol/doc-typesNone โ€” publicNot under /api/v1. Optional country query parameter. Lists the curated set for a country
POST/api/v1/participants/{participant_id}/registerparticipants:manageOptional request body: {"document_types": [...]}. With no body, the country default set is published and nothing is removed. With a list, everything you leave out is deleted from the SMP
POST/api/v1/participants/{participant_id}/deregisterparticipants:managePOST, not DELETE
GET/api/v1/participants/{participant_id}/smp-statusAuthenticatedA single hyphenated path segment
DELETE/api/v1/participants/{participant_id}participants:manage204 on success; soft-deletes the record. A still-published participant is deregistered first, and a refused deregistration answers 502 SMP_DEREGISTRATION_FAILED without deleting anything โ€” see Delete the participant record

GET /peppol/doc-types is the one endpoint here that is not under /api/v1 and needs no API key.

There is no capabilities-editing route. See "Changing document capabilities" above.

Next Stepsโ€‹