Sending & webhooks
Send invoices on behalf of your customers, and keep your UI in sync with lifecycle webhooks.
Sending as a customer
Send an invoice on a customer's behalf with the standard
POST /v1/invoices endpoint — just add a sender that points to one
of your customers. Identify them by their getpeppr legalEntityId or by your own
externalSubTenantId.
- Authoritative seller — the supplier identity (name, country, Peppol ID)
is taken from the customer's verified legal entity. Any
fromin the payload is accepted but stripped (no error returned), so you can't accidentally mis-state the sender. - Send gate — the customer must be
activeon production (verified, attested, and registered on the network), orverifiedin sandbox. Otherwise the send is rejected with422. - Requires a master key with the
legal_entities:send_asscope.
sender field is simply ignored. Send-as activates only for a master key.
curl https://api.getpeppr.dev/v1/invoices \
-H "Authorization: Bearer sk_live_your_master_key" \
-H "Content-Type: application/json" \
-d '{
"sender": { "externalSubTenantId": "customer_8412" },
"to": {
"peppolId": "0208:0123456789",
"name": "Riverside Clinic",
"country": "BE"
},
"lines": [
{ "description": "Consultation", "quantity": 1, "unitPrice": 90.00, "taxPercent": 0 }
]
}'Lifecycle webhooks
getpeppr pushes a webhook on each meaningful customer transition, so your platform UI stays in sync without polling. They ride the same delivery channel as your other webhooks — HMAC-signed, with automatic retries. See Webhooks for signature verification and retry behaviour.
Events
legal_entity.registered— a customer reached a verified or active state (statustells you which).legal_entity.verification_failed— registry mismatch or not found.legal_entity.awaiting_authz— an attestation request is awaiting the customer.
attested, provisioning) are not pushed as
separate events — going live is signalled by legal_entity.registered with
status: "active". Poll GET /v1/legal-entities/:id if you need the
fine-grained step.
Payload
Each event's data carries the fields below. peppolId is the
customer's scheme and identifier joined by a colon (or null if not yet set).
subTenantId— yourexternalSubTenantIdfor this customer. You set this at creation, so it's present for sub-tenants you created via the API.legalEntityId— the getpeppr legal entity id.peppolId— the customer's Peppol identifier as"scheme:value", ornull.status— one ofverified,verification_failed,awaiting_authz,active.environment—sandboxorproduction.reason— on failures:name_mismatchornot_found.occurredAt— ISO 8601 timestamp of the transition.
subTenantId — it's the same reference
you supplied at creation, so no extra lookup is needed.
{
"id": "evt_1a2b3c",
"type": "legal_entity.registered",
"createdAt": "2026-06-01T10:05:00.000Z",
"data": {
"subTenantId": "customer_8412",
"legalEntityId": "7c9a1b34-2d5e-4f60-8a1b-9c2d3e4f5a6b",
"peppolId": "GB:CRN:12345678",
"status": "active",
"environment": "production",
"occurredAt": "2026-06-01T10:05:00.000Z"
}
}