The sub-tenant is not in a state where an attestation can be issued. The body names why.
1 operation
- POST /v1/legal-entities/{id}/attestation
The 216 results this API can return, with the status each one always carries, what it means and what to do next. A code never changes meaning, never moves to a different status and is never reused — branch on it.
Getpeppr-Result-CodeGetpeppr-Result-MessageGetpeppr-RetryableGetpeppr-RemediationGetpeppr-Request-IdGetpeppr-Result-Docs216 codes
The sub-tenant is not in a state where an attestation can be issued. The body names why.
The attestation email could not be sent. Retry to mint a fresh link.
An attestation request was sent to the sub-tenant. It is now awaiting their confirmation.
This sub-tenant has no Peppol identifier to attest.
The attestation request is missing a required field or carries one in the wrong shape.
The API key is not valid for this environment, or has been revoked.
Missing or malformed Authorization header. Send `Authorization: Bearer <api key>`.
Too many failed authentication attempts from this address. Wait and retry.
This endpoint needs a master API key on a platform account. Request access at hello@getpeppr.dev.
This API key type is not authorised for this operation.
Bank account created.
Bank account deleted.
Bank account list returned.
A bank account needs a name. Send `name` as a string.
No bank account matches this identifier on this account.
Bank account returned.
Bank account updated.
No capability matrix is registered for the active provider.
Provider capability matrix returned.
Contact created.
Contact deleted.
Contact list returned.
A contact needs a name. Send `name` as a string.
No contact matches this identifier on this account.
Contact returned.
Contact updated.
The Peppol identifier is not in a recognised format.
The Peppol identifier needs both a scheme and an identifier.
The participant is registered on the Peppol network.
The participant is registered, resolved through the provider rather than the registry.
No Peppol participant is registered under this identifier.
The directory search completed.
The directory search parameters are missing or invalid. The response body names which.
documentId and invoiceId must match when both are provided.
A date query parameter is malformed. Use YYYY-MM-DD.
A query parameter was repeated or empty. Send each one exactly once.
Event list returned.
One or more dependencies are unavailable.
All health checks passed.
A request with this key is in progress and its result could not be read. Retry shortly.
An identical request with this Idempotency-Key is still in flight. Retry shortly.
The Idempotency-Key header is present but blank, so it cannot protect this request. Send a non-blank key, or omit the header.
This Idempotency-Key was already used for a different request. Use a new key.
Replayed a stored response recorded before result codes existed.
Replayed a stored response recorded before result codes existed.
Replayed a stored response recorded before result codes existed.
Account Peppol identity returned.
This account's Peppol identity is not verified, so production sending is refused.
An amount is outside the range this API records.
The request body must be a JSON object describing one invoice.
The buyer address needs a street, a city and a postal code.
A national Peppol rule refuses this invoice. The body names the rule and how to fix it.
The invoice was accepted and submitted to the Peppol network.
An identical invoice was sent moments ago. The body names the earlier one.
The requested export format is not one this endpoint produces.
The invoice document was returned in the requested format.
A field is longer than this API records. The body names which.
An allowance or charge amount is negative or not a finite number.
A line's base quantity is zero, negative or not a finite number.
A country code is not on the network's published list (BR-CL-14).
A tax rate on this invoice is not one the network accepts for the chosen category.
A query parameter is repeated or empty.
That VAT category is not one the network recognises.
The invoice number is longer than this API records.
The invoices were listed.
The request body is not valid JSON.
The request must name the state to record, as a string.
That state is not one this endpoint records. The body lists the accepted ones.
The invoice state was recorded.
A derived total is not a finite number. Check the line amounts.
No invoice is visible under this id for this account and environment.
The chosen payment means needs a mandate this invoice does not carry.
This platform account has no live billing contract, so it cannot send.
Production access for this account has expired. Contact support to restore it.
The invoice was read.
The recipient is not registered in the Peppol Directory, and strict checking was requested.
The recipient's Peppol identifier is required, in the form scheme:id.
The invoice is missing a required field. The body names which.
This account has no Peppol identity registered, so it cannot send in production.
The sender's tax country could not be resolved, and it decides which national rules apply.
This sub-tenant has no VAT identifier registered, which a tax-bearing invoice requires.
The invoice record is unavailable. Contact support with the document id.
That payment means has no route on the Peppol network. The body lists the ones that do.
That VAT category is valid but has no route on the Peppol network.
The request body is not valid JSON.
The document was accepted and submitted to the Peppol network unchanged.
The document's structure is too large to validate at bounded cost. Split it up.
An identical document was sent moments ago. The body names the earlier one.
The request must carry a `file` field holding the base64-encoded document.
The request must carry a `filename` string.
The `file` field is not valid base64. It is never repaired before sending.
The supplied document is not accepted as XML.
This account has no registered identifier to send this document under.
The supplied document is not a UBL Invoice or CreditNote.
This platform account has no live billing contract, so it cannot send.
Production access for this account has expired. Contact support to restore it.
The recipient's Peppol identifier is required: the document does not decide where it goes.
This account has no Peppol identity registered, so it cannot send in production.
The named sub-tenant has no registered Peppol identifier to send under.
This account has several registered identifiers and the document does not say which applies.
The supplier in the document is not the sub-tenant named in `sender`.
The supplier identifier in the document is not registered to this account.
The document is not valid UTF-8. It is sent untouched, so it must be readable as given.
The document's number, date or currency could not be read.
The document's recipient name or country could not be read.
The document declares an XML encoding other than UTF-8. Re-encode it and submit again.
The document breaks fatal Peppol rules and was not sent. The body names them.
Document validation is unavailable, so nothing was sent. Retry shortly.
Correcting a registered identifier archives and recreates the entity, which needs the archive scope.
The sub-tenant legal entity was archived.
The action could not be recorded in the audit trail and was refused. Retry, then contact support.
A creation for this external id is already in flight. Retry shortly.
This Peppol identifier is already registered on another legal entity.
A registered Peppol identifier cannot be changed in place. Archive the entity and recreate it.
The sub-tenant legal entities were listed.
No sub-tenant legal entity is visible under this id for this platform account.
The Peppol provider is not configured for this environment. Contact support.
The sub-tenant legal entity was read.
The request is missing a required field or carries one in the wrong shape.
This sandbox account has reached its sub-tenant legal entity limit.
The sub-tenant legal entity was created. Verification continues asynchronously.
A sub-tenant legal entity already exists for this external id.
Lookup CTA click recorded.
The Peppol Directory is temporarily unavailable. Try again shortly.
The Peppol identifier is not in a recognised format.
The participant is registered on the Peppol network.
No participant is registered under this identifier.
The search query is missing or outside the accepted length.
The participant search completed.
One or more fields fall outside the length the provider accepts. The body lists them.
The legal entity was created.
The existing legal entity was updated.
The Peppol identifier is not acceptable for this scheme. The body names why.
The Peppol scheme is missing, too long, or not a string.
Registering a production Peppol identifier requires dashboard attestation by a person.
The Peppol provider is not configured for this environment. Contact support.
This scheme has no registry behind it, so it cannot be verified and is limited to the sandbox.
A required field is missing or is not of the expected type. The body names which.
This scheme is not on the Peppol network: a participant registered under it is reachable by nobody.
getpeppr could not authenticate with the Peppol provider. Contact support.
The provider already holds this resource. Choose a different value or contact support.
The Peppol provider is not configured for this environment. Contact support.
The Peppol provider does not support this operation.
The provider rejected this document. The response body names what to correct.
The provider rejected this request as malformed. Check the request and retry.
The provider has no record of this resource.
The Peppol provider could not be reached just now. Retry shortly.
The Peppol provider is throttling requests. Wait and retry.
The Peppol provider is temporarily unavailable. Retry shortly.
The Peppol provider returned an unexpected response. Quote the request id to support.
Rate limit exceeded for this account. Retry after the interval in Retry-After.
Too many attestation requests. Retry after the interval in Retry-After.
Directory lookup rate limit exceeded. Retry after the interval in Retry-After.
Rate limit exceeded for this API key. Retry after the interval in Retry-After.
Too many legal entity creation requests. Retry after the interval in Retry-After.
Too many subscribe attempts from this address. Wait and retry.
Too many onboarding attempts. Retry after the interval in Retry-After.
Too many requests from this address. Wait and retry.
Too many directory lookups from this address. Wait and retry.
Too many directory searches from this address. Wait and retry.
Too many unsubscribe requests from this address. Wait and retry.
Validation rate limit exceeded. Retry after the interval in Retry-After.
The legalEntityId query parameter must be a UUID.
Received document list returned.
No received document matches this identifier on this account.
Received document returned.
Received document UBL returned.
Request body exceeds the maximum size accepted by this endpoint.
The request body is not valid JSON.
This HTTP method is not allowed on this endpoint. See the Allow header.
Answered by the API edge: every /v1 path, for a method it does not implement
No API endpoint matches this host and path.
Answered by the API edge: any /v1 path no route serves
CORS preflight accepted.
Answered by the API edge: every /v1 path, on OPTIONS
`sender` must carry exactly one of legalEntityId or externalSubTenantId.
No sub-tenant legal entity is visible under this reference for this platform account.
This sub-tenant's Peppol identity is not in a state that allows sending.
An unexpected error occurred. Quote the request id when contacting support.
Transport list returned.
Transport configuration is managed automatically and cannot be changed through the API.
No transport matches this code.
Transport returned.
Transport type list returned.
The unsubscribe could not be recorded. Try again shortly.
Unsubscribe confirmation page returned.
Unsubscribed from non-critical email.
This link's token is not valid or has expired.
This link is missing its token.
The invoice was checked. The body carries the verdict and any errors.
Attachment content must be raw base64, without a data URI prefix.
An attachment decodes to more bytes than the validator accepts.
The invoice was checked against the network rules. The body carries the verdict.
Validation is temporarily unavailable. Quote the request id when contacting support.
The request body must be a JSON object describing one invoice.
The invoice is missing fields the validator needs before it can judge anything.
The invoice carries more attachments than the validator accepts.
The invoice carries more line items than the validator accepts.
Document type declarations are not accepted.
The document's structure is too large to validate at bounded cost. Split it up.
Document validation is temporarily unavailable. Retry shortly.
The request must carry a `file` field holding the base64-encoded document.
The `file` field is not valid base64. It is never repaired before judging.
The supplied document is not accepted as XML.
The supplied document is not a UBL Invoice or CreditNote.
The document is not valid UTF-8. It is read untouched, so it must be readable as given.
The document declares an XML encoding other than UTF-8. Re-encode it and submit again.
The document was judged against the Peppol rulebooks. The body carries the verdict.
API version information returned.
A request reaches our code through a hosting platform, and the platform answers a few of them itself. Those responses carry none of the headers above — no request id, no result code — because our API never ran. They are plain text or HTML rather than JSON, so a client that assumes a JSON body will fail to parse them.
To tell them apart, check for the marker in the third column: the status alone will not, since 405 appears on both sides. One row has no response to inspect at all — the connection is cut before anything is sent, so it surfaces in your client as a transport or protocol error rather than as a status. Treat that one by its cause, listed under “What to do”, not by inspecting a response you will never receive.
| When | Response | How to recognise it | What to do |
|---|---|---|---|
| A BREW or PROPFIND request. Both are refused by the edge before any of our code runs. | 405text/plain; charset=utf-8 | x-vercel-error: INVALID_REQUEST_METHOD | Use one of the methods the endpoint documents. The response body carries a Vercel request id — quote that, not a getpeppr request id, because none was issued. |
| A TRACE request. | 405text/plain; charset=utf-8 | x-vercel-error: NOT_ALLOWED | TRACE is refused by the hosting platform and cannot be enabled; use one of the methods the endpoint documents. |
| A path containing an invalid percent-escape, over HTTP/1.1. | 400text/plain; charset=utf-8 | no x-vercel-id and no server header, plus Connection: close | Percent-encode path segments correctly before sending; the request never reached getpeppr, so retrying it unchanged cannot succeed. |
| The same invalid percent-escape, over HTTP/2. | no response — the connection is cut | HTTP/2 stream reset — PROTOCOL_ERROR, no response headers | Same cause as the HTTP/1.1 case, but it surfaces as a connection error rather than a status: fix the encoding rather than treating it as a network fault worth retrying. |
| Traffic the Vercel firewall judges suspicious from this client address.Not guaranteed to reproduce — it depends on traffic patterns, so treat it as possible rather than as a rule. | 403text/html; charset=utf-8 | x-vercel-mitigated: challenge | Pause before retrying. Ordinary requests from the same client are refused while this lasts, so an unchanged request failing here is not evidence that the request itself is wrong; the same request succeeded once the mitigation had cleared. |
Measured against the deployed API, most recently on 2026-08-27. This list covers what we have observed and tested, not everything a platform can possibly do.