Validation
Validate invoices before sending to catch errors instantly — no network call needed.
getpeppr validate invoice.json to validate offline
without writing code. See the CLI docs.
Client-side Validation
The SDK includes a built-in validator that checks your invoice against Peppol BIS 3.0 business rules before making any API call. This catches errors instantly and saves you a round-trip to the server.
How It Works
Call peppol.validate() with the same payload you'd pass to
peppol.invoices.send(). The method returns a result object
with valid, errors[], and warnings[].
Errors vs Warnings
- Errors — blocking issues that prevent sending. Must be fixed.
- Warnings — non-blocking suggestions for better compliance. Sending still works.
send(). If validation fails,
a PeppolValidationError is thrown — see
Error Handling.
import { Peppol } from "@getpeppr/sdk";
const peppol = new Peppol({ apiKey: "sk_sandbox_..." });
// Validate locally before sending — catches errors instantly
const result = peppol.validate({
number: "INV-2026-042",
to: { name: "ACMEDIA", peppolId: "0208:0685660237", street: "Rue de la Loi 200", city: "Brussels", postalCode: "1000", country: "BE" },
lines: [
{ description: "Consulting Q1", quantity: 40, unitPrice: 125, vatRate: 21 },
],
});
if (!result.valid) {
for (const error of result.errors) {
console.error(`[${error.field}] ${error.message}`);
// e.g. "[to.street] Street address is required for the buyer"
if (error.suggestion) {
console.log(` Tip: ${error.suggestion}`);
// "Add the buyer's street address"
}
}
}
// Also returns warnings for non-blocking suggestions
for (const warning of result.warnings) {
console.warn(`[${warning.field}] ${warning.message}`);
}Response Format
The validation result contains structured error and warning objects with
field paths that point to the exact location of each issue.
Error Object
field— dot-notation path (e.g.from.vatNumber,lines[0].unitPrice)message— human-readable description of the issuesuggestion— optional fix recommendation
field path to highlight specific form fields in your UI,
giving users precise feedback on what to fix.
{
"valid": false,
"errors": [
{
"field": "from.vatNumber",
"message": "VAT number recommended for invoices > EUR 400",
"suggestion": "Add vatNumber to the seller party"
}
],
"warnings": [
{
"field": "paymentIban",
"message": "IBAN recommended for faster payment processing"
}
]
}Server-side Validation
Use POST /v1/validate/server when you want the gateway to run the same SDK validation
stack server-side. The endpoint does not send invoices to Storecove; it checks the payload,
verifies UBL XML generation, and runs offline Peppol business-rule validation.
200 with valid: false. Malformed JSON,
missing minimum fields, auth failures, and rate limits still return non-2xx errors.
curl -X POST https://api.getpeppr.dev/v1/validate/server \
-H "Authorization: Bearer sk_sandbox_abc123..." \
-H "Content-Type: application/json" \
-d '{
"number": "INV-2026-042",
"to": { "name": "ACMEDIA", "peppolId": "0208:0685660237", "street": "Rue de la Loi 200", "city": "Brussels", "postalCode": "1000", "country": "BE" },
"lines": [
{ "description": "Consulting Q1", "quantity": 40, "unitPrice": 125, "vatRate": 21 }
]
}'{
"valid": false,
"errors": [
{
"field": "to.street",
"message": "Street address is required for the buyer",
"ruleId": "BR-50"
}
],
"warnings": [],
"ubl": {
"valid": true,
"errors": []
},
"xsd": {
"valid": true,
"errors": [],
"note": "Deprecated compatibility field. This endpoint verifies UBL XML generation but does not run a standalone XSD validator."
},
"schematron": {
"valid": true,
"errors": [],
"warnings": []
}
}