Menu
Cookbooks
API reference
- Overview
- Companies
- Customers
- Invoices
- Articles
- Suppliers
- Supplier invoices
- Supplier payment files
- Expense claims
- Transactions
- Reconciliation
- Bank accounts
- Journal entries
- Voucher gap explanations
- Fiscal periods
- Accounts
- Fixed assets
- Documents
- Inbox items
- Dimensions
- Employees
- Salary runs
- Reports
- Imports
- Compliance check
- Skatteverket
- Peppol
- Webhooks
- Operations
- Health
Peppol
Peppol e-invoicing for the company: participant registration status, registering to receive, and requesting access. Sending an invoice over Peppol is on the invoices page.
Endpoints
GET/api/v1/companies/:companyId/peppol/registration: Read the company's Peppol receiving status: access grant, eligibility and registration.POST/api/v1/companies/:companyId/peppol/access-request: Ask the operators to switch on Peppol for the company (sending, optionally receiving).POST/api/v1/companies/:companyId/peppol/registration: Register the company as a Peppol participant so it can receive e-invoices.
GET /api/v1/companies/:companyId/peppol/registration
peppol.get-registration · scope companies:read
Read the company's Peppol receiving status: access grant, eligibility and registration.
Whether this environment has an access point and whether it supports receiving, the company's Peppol access grant (sending cap, receiving slot), whether the company can be registered at all (a 10-digit organisation number that is not a personnummer, a company name), and the registration of its participant id (0007 + org number) with its status and last error.
Use when: Before POST /peppol/registration, or to explain why the company does not receive e-invoices.
Don't use for: Sending (GET /invoices/{id}/peppol checks an invoice) or reading received e-invoices (they arrive in the invoice inbox).
Pitfalls
- participant.ok=false with PEPPOL_REGISTRATION_PERSONAL_NUMBER means a sole trader identified by personnummer: it cannot be published in the Peppol directory.
- registration.can_retry says whether registering again can help; a permanent verdict (e.g. CONNECTOR_PEPPOL_PARTICIPANT_TAKEN) needs support.
Risk: low · Idempotent: yes · Reversible: no · Dry-run supported: no
Response fields
| Name | Type |
|---|---|
transport | object |
receiving_supported | boolean |
access | object |
participant | object |
registration | object | null |
Example response
{
"data": {
"transport": {
"available": true,
"provider": "qvalia",
"reason": null
},
"receiving_supported": true,
"access": {
"status": "enabled",
"send_enabled": true,
"receive_enabled": true,
"max_sends": 50,
"sent_count": 3,
"remaining_sends": 47
},
"participant": {
"ok": true,
"code": null
},
"registration": {
"registration_id": "4c2d…",
"provider": "qvalia",
"participant_scheme": "0007",
"participant_identifier": "5595386219",
"status": "registered",
"registered_at": "2026-09-26T10:00:00Z",
"deregistered_at": null,
"last_error_code": null,
"stale_pending": false,
"can_retry": false,
"updated_at": "2026-09-26T10:00:00Z"
}
},
"meta": {
"request_id": "req_…",
"api_version": "2026-05-12"
}
}
POST /api/v1/companies/:companyId/peppol/access-request
peppol.request-access · scope companies:write
Ask the operators to switch on Peppol for the company (sending, optionally receiving).
Peppol is locked per company until the operators grant it (every transmission is billed per document and every receiving id uses a contracted slot). This records the request and notifies the operators by e-mail; they enable it with a sending cap and, when wants_receiving is true, a receiving slot. Idempotent: a second request keeps the first. Dry-runnable.
Use when: GET /invoices/{id}/peppol or GET /peppol/registration reports PEPPOL_ACCESS_REQUIRED and the user wants Peppol.
Don't use for: Registering the participant id once access is granted (POST /peppol/registration).
Pitfalls
- A company that already has access answers 409 PEPPOL_ACCESS_ALREADY_ENABLED; ask support for a higher cap or a receiving slot instead.
- Nothing is enabled immediately: poll GET /peppol/registration for access.status=enabled.
Risk: medium · Idempotent: yes · Reversible: no · Dry-run supported: yes
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
dry_run | string | no | true (any case) previews the write without committing it, like the X-Dry-Run: true header. Any other value commits. |
Request body
| Name | Type | Required | Description |
|---|---|---|---|
note | string | no | Free text for the operators (what the company needs Peppol for). |
wants_receiving | boolean | no | True when the company also wants to receive e-invoices (a receiving slot). |
Response fields
| Name | Type | Description |
|---|---|---|
access | object | |
created | boolean | False when an open request already existed. |
Example request
{
"wants_receiving": true,
"note": "Vi fakturerar kommuner."
}
Example response
{
"data": {
"access": {
"status": "requested",
"send_enabled": false,
"receive_enabled": false,
"max_sends": null,
"sent_count": 0,
"remaining_sends": null
},
"created": true
},
"meta": {
"request_id": "req_…",
"api_version": "2026-05-12"
}
}
POST /api/v1/companies/:companyId/peppol/registration
peppol.register · scope companies:write
Register the company as a Peppol participant so it can receive e-invoices.
Publishes the company's participant id (scheme 0007 + organisation number) with a business card (name, country, city, VAT number) at the access point, for BIS Billing 3 invoices and credit notes. Received e-invoices then arrive in the invoice inbox. Needs the operators' receiving grant. A pending attempt older than five minutes is retired and retried. Owner/admin only. The dry run checks everything as reads and contacts no network.
Use when: The company wants suppliers to send it e-invoices over Peppol and GET /peppol/registration shows receive_enabled.
Don't use for: Sending e-invoices (that needs no registration of the buyer side here) or asking for access (POST /peppol/access-request).
Pitfalls
- Without the grant: 403 PEPPOL_ACCESS_REQUIRED; with sending but no receiving slot: 403 PEPPOL_RECEIVING_NOT_ENABLED.
- A personnummer-based sole trader answers 422 PEPPOL_REGISTRATION_PERSONAL_NUMBER: it would publish personal data in the directory.
- 502 PEPPOL_REGISTRATION_FAILED is operational and retryable; 422 PEPPOL_REGISTRATION_REJECTED is a verdict on the identifier (details.code says which), do not retry it.
- 409 PEPPOL_REGISTRATION_CAP_REACHED: every contracted receiving slot is taken; sending still works.
- Owner or admin only: a member key gets 403 FORBIDDEN.
Risk: high · Idempotent: yes · Reversible: no · Dry-run supported: yes
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
dry_run | string | no | true (any case) previews the write without committing it, like the X-Dry-Run: true header. Any other value commits. |
Response fields
| Name | Type |
|---|---|
registration | object |
Example response
{
"data": {
"registration": {
"registration_id": "4c2d…",
"provider": "qvalia",
"participant_scheme": "0007",
"participant_identifier": "5595386219",
"status": "registered",
"registered_at": "2026-09-26T10:00:00Z",
"deregistered_at": null,
"last_error_code": null,
"stale_pending": false,
"can_retry": false,
"updated_at": "2026-09-26T10:00:00Z"
}
},
"meta": {
"request_id": "req_…",
"api_version": "2026-05-12"
}
}