Skip to content

Sub-tenant lifecycle

How each customer moves from created to live on Peppol — every status, and what sandbox and production each require.

The customer journey

Each supported customer you onboard moves through the same API lifecycle. You drive it with a few API calls; getpeppr runs the regulated steps in between.

  1. 1. Create — POST /v1/legal-entities with the customer's company details and Peppol identifier. We validate the format and start registry verification.
  2. 2. Verify — where automatic verification is available, we check the identifier with the relevant verification source and match the declared company name when that source returns one. (verifying → verified)
  3. 3. Authorise (production) — request an attestation; the customer confirms, on a getpeppr-signed page, that they authorise you to register them on the Peppol network and to send and receive their electronic invoices. (awaiting_authz → attested)
  4. 4. Publish — we attach the verified identity at Storecove. This is the provider-local registration used by the existing outbound send gate; it is not proof that another Access Point can find the customer.
  5. 5. Discover — from the official SML record, we follow the advertised SMP and require the exact participant, Invoice BIS Billing 3.0 metadata, and an active AS4 v2 endpoint with a current, non-revoked OpenPeppol G3 certificate. (provisioning)
  6. 6. Receive-ready — only that public cross-Access-Point proof changes the customer to active and emits legal_entity.registered.
Read a customer's status any time with GET /v1/legal-entities/:id. Use lifecycle webhooks for actionable events, and poll for fine-grained intermediate states that are not emitted.
Check a customer's status
curl https://api.getpeppr.dev/v1/legal-entities/7c9a1b34-2d5e-4f60-8a1b-9c2d3e4f5a6b \
  -H "Authorization: Bearer sk_live_your_master_key"
Response
{
  "id": "7c9a1b34-2d5e-4f60-8a1b-9c2d3e4f5a6b",
  "externalId": "customer_be_001",
  "companyName": "Your Customer SRL",
  "country": "BE",
  "identifier": { "scheme": "0208", "value": "YOUR_10_DIGIT_KBO" },
  "status": "awaiting_authz",
  "networkDiscovery": { "state": "pending", "attempts": 0 },
  "environment": "production",
  "createdAt": "2026-06-01T10:00:00.000Z"
}

Status reference

The status field on a customer tells you exactly where they are in the pipeline. These six apply in every environment, plus two that only the sandbox produces:

Sub-tenant status values in every environment
StatusMeaning
pendingCreated; verification queued or not yet conclusive.
verifyingBeing checked against the relevant automatic verification source.
verifiedIdentity confirmed. Transitional: as soon as publication starts the customer reads provisioning, then active. This alone proves neither Storecove publication nor receive readiness.
unsupported_schemeNo automatic validator is active for this identifier scheme. No registry rejected the customer and no work remains in progress; contact support before sending.
verification_failedRegistry name mismatch or identifier not found.
archivedOff-boarded. No longer listed and cannot send.
no_registrySandbox only. The identifier's scheme has no registry behind it (9915), so nothing was verified and nothing failed. It sends in the sandbox; production refuses such identifiers at creation.
registration_failedSandbox only. Identity verification succeeded, but the network (SMP) registration failed — most often because the same value is already registered on the shared test network.

Authorisation and receive readiness

Production alone adds the authorisation states. Storecove publication and public cross-Access-Point discovery can surface provisioning and active in both environments. These statuses layer on top:

Authorisation and receive-readiness status values
StatusMeaning
awaiting_authzAttestation requested; waiting for the customer to confirm.
expiredThe attestation request lapsed before the customer confirmed.
attestedCustomer authorised. Storecove publication can begin.
provisioningStorecove publication or public receive discovery is still in progress. A temporary provider error is retried automatically while the status stays here.
awaiting_releaseCustomer authorised, but another Peppol access point still holds the address. getpeppr checks every minute and registers it as soon as it is released, then the status moves on to active. registrationDetail.heldBy names that access point's SMP host when known, and registrationDetail.waitingUntil says when getpeppr stops waiting (30 days). Ask the previous provider to remove the address; nothing else is needed from you.
activeReceive-ready: the exact public SML → SMP → Invoice metadata → active AS4 path and its OpenPeppol G3 certificate were verified. A Norwegian customer can also send only when vatRegistration.vatNumberAdded is true (see Norwegian customers).
provisioning_failedNetwork registration failed and is no longer retried automatically: the address was still held elsewhere when the 30-day wait ended, the provider refused it, or provider errors kept it from completing for 30 days. registrationDetail.reason says which (already_registered, invalid_format or provider_error). Call POST /v1/legal-entities/:id/attestation again to retry: getpeppr answers 202 and starts a new attempt of up to 30 days (a definitive refusal by the provider ends it earlier), with no new email and no new confirmation (the request body is validated as for a first request: send contactEmail).

Receive discovery detail

Every Legal Entity response includes networkDiscovery. It reports the receive-only check without exposing SMP URLs, DNS answers, XML, or another copy of the participant ID. Verified entries are checked again every 24 hours so later certificate expiry, revocation, or publication loss cannot stay marked receive-ready indefinitely.

  • state — pending, verified, or failed. A failed check remains on a slower automatic retry schedule.
  • attempts — consecutive public discovery attempts started since the latest success; it resets to 0 whenever discovery verifies the customer.
  • checkedAt — when the latest attempt finished, when available.
  • nextAttemptAt — when another automatic attempt is due, when available.
  • error — a bounded machine-readable reason on failed; no raw network response is returned.
Storecove registration alone is not proof that a third-party Access Point can discover the customer. Outbound sending remains independent: it keeps its existing identity, authorisation, and Storecove-publication gates and does not read networkDiscovery.

Sandbox vs production

The pipeline has the same shape everywhere, but production adds the steps that make an identity legally real on the network.

  • Sandbox — no attestation step. After identity verification, getpeppr publishes on the test network and checks public discovery there. Identity verified alone is not receive-ready.
  • Production — a customer must be verified and authorised (attestation) before Storecove publication; getpeppr then proves the public live-network discovery path before returning active.
Attestation is a production-only concept. Calling the attestation endpoint with a sandbox key returns 400. Receive discovery applies in both environments. Outbound sending remains independent and may become available while receive status is still provisioning.

Outcomes and terminal states

Three states need action; one is an intentional end state.

  • verification_failed — the registry returned a name mismatch or didn't find the identifier. The response carries a verificationDetail.reason of name_mismatch or not_found. The customer can't go live until it's resolved. A not_found has more than one cause, and verificationDetail.registryStatus helps tell them apart: when it reads inactive, the registry does know the company but doesn't consider it active — struck off, in liquidation, or not yet active. Re-sending the same details won't change the answer until the registry itself changes it, so the customer generally has to supply a company that is trading today. When the field is absent, all it means is that we have no such finding to show — never that none exists, and never that the company is unknown. The registry may have no entry, may have been unreachable, our team may have reviewed an earlier finding, or there may simply be no inactive finding on record — a valid VAT registration can verify a company on its own, so the national registry isn't always consulted, and isn't always what settles the answer. So check at the customer's own national registry that the company is trading before you go looking for a typo, and treat this field as a positive signal only.
  • unsupported_scheme — automatic verification is unavailable for this identifier scheme. This is terminal for your current request, not a failed registry check and not a reason to keep polling. Contact support before sending. The internal row remains resumable if support for the scheme is added later.
  • registration_failed — identity verification succeeded, but sandbox network registration did not. Read registrationDetail.reason on GET or LIST: already_registered, invalid_format, or provider_error. This diagnostic is stable and deliberately coarse; raw provider errors stay private.
  • expired — an attestation request wasn't completed before it expired (see expiresAt on the attestation response). Request a new one to resend the email.
  • archived — intentional: you off-boarded the customer with a DELETE. They drop out of lists and can no longer send.

Network identifiers and VAT

When getpeppr registers a customer on the Peppol network, it attaches the identifier you declared at creation — and, where VAT registration can be proven, the matching VAT identifier as well. For Belgian customers (0208), the BE:VAT identifier is derived from the enterprise number and registered automatically. For Swedish customers (0007), the SE:VAT identifier is derived from the organisation number; because the Swedish company registry does not prove VAT registration (momsregistrering), getpeppr first confirms the derived VAT number against VIES (the EU VAT registry) before publishing it in production. For Norwegian customers (0192), the MVA number (NO:VAT) is added only after the Norwegian business register confirms, at registration time, that the company is in the VAT Register; it is never announced as a Peppol address (see Norwegian customers). In every case there is nothing extra to send in your payload.

The VAT identifier matters at send time: a Peppol invoice that carries VAT — including 0% rates and tax-exempt invoices — is rejected when the sending identity has no registered VAT number.

getpeppr checks VAT registration when it registers the identifier, not afterwards. If a customer's VAT registration ends — in any country — acting on it is yours: in sandbox, archive the legal entity and create it again; in production, contact support. The accuracy and legality of the invoices your customers send remain theirs and yours (Terms §5).

If a send returns 422 with "The sub-tenant Legal Entity selected by 'sender' has no VAT identifier registered", the customer's entity predates automatic VAT registration or its verification could not prove VAT registration. Contact support — verified entities can be backfilled without re-onboarding, except in Norway: a Norwegian entity registered without its MVA number (for example, one that joined the VAT Register afterwards) is not backfilled automatically. In sandbox, archive it and create it again; in production, contact support.