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

Every customer you onboard moves through the same managed pipeline. You drive it with a few API calls; getpeppr runs the regulated steps in between.

  1. 1. CreatePOST /v1/legal-entities with the customer's company details and Peppol identifier. We validate the format and start registry verification.
  2. 2. Verify — we check the identifier against the country's business registry and match the declared company name. (verifying → verified)
  3. 3. Authorise (production) — request an attestation; the customer confirms, on a getpeppr-signed page, that they authorise invoicing on their behalf. (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 — or let the lifecycle webhooks push each transition to you, no polling required.
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_8412",
  "companyName": "Bright Health Ltd",
  "country": "GB",
  "identifier": { "scheme": "GB:VAT", "value": "gb123456789" },
  "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:

Sub-tenant status values in every environment
StatusMeaning
pendingCreated; verification queued or not yet conclusive.
verifyingBeing checked against the country's business registry.
verifiedIdentity confirmed. 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.

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.
activeReceive-ready: the exact public SML → SMP → Invoice metadata → active AS4 path and its OpenPeppol G3 certificate were verified.
provisioning_failedStorecove publication failed and will be retried.

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.

  • statepending, 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.
  • archivedintentional: 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. In both cases 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.

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.