Skip to content

Validation

Validate invoices before sending to catch errors instantly — no network call needed.

Prefer the terminal? Use 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.
Validation is also run automatically when you call 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 issue
  • suggestion — optional fix recommendation
Use the field path to highlight specific form fields in your UI, giving users precise feedback on what to fix.
Validation Result
{
  "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.

Validation findings return HTTP 200 with valid: false. Malformed JSON, missing minimum fields, auth failures, and rate limits still return non-2xx errors.
Validation requests use a dedicated per-key rate-limit bucket, separate from send/list traffic. Server-side validation caps embedded attachment content at 2 MB decoded per attachment before UBL generation.
Server validation
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 }
    ]
  }'
Server Validation Result
{
  "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": []
  }
}