CLI
Validate, scaffold, and convert offline — or send to Peppol with one command.
Installation
Install @getpeppr/cli globally or run it directly with npx.
Install globally
npm install -g @getpeppr/cliOr use npx (no install)
npx @getpeppr/cli validate invoice.jsonScaffold an Invoice
Generate a starter JSON file with all required fields pre-filled — a Belgian seller, the Belgian sandbox test receiver as buyer, two invoice lines. Ready to edit, validate, and send.
# Default — creates invoice.json
getpeppr init
# Custom filename
getpeppr init my-invoice.json
# Credit note template
getpeppr init --credit-note
# Overwrite an existing file
getpeppr init --force| Flag | Description |
|---|---|
[filename] | Output filename (default invoice.json) |
--credit-note | Generate a credit note template instead of an invoice |
--force | Overwrite an existing file |
Validate an Invoice
Pass a JSON file to getpeppr validate to check it against three validation engines:
- Structure — required fields, types, and format checks
- Offline Checks — 40 registered partial pre-flight checks: exact network-rule equivalents plus explicit
GETPEPPR-*diagnostics; the legacy provider-capability diagnosticunsupported_vat_categorycan also appear outside that count - Country Rules — Belgium, France, Italy, Netherlands, Germany
getpeppr validate invoice.jsonExample output
Validating: invoice.json
── Structure ──────────────────────────────
✓ No errors
⚠ to.vatNumber — Buyer VAT number not provided. May be required for B2B.
── Offline Checks (partial) ───────────────────
✓ No findings
── Country Rules ────────────────────────────
⚠ No structured communication reference (BE-02)
── Summary ──────────────────────────────────
✓ Pre-flight checks passed (2 warnings)validateInvoice, validateSchematron, validateCountryRules). This offline pass catches common issues; it is not a Peppol conformance verdict. Sending invoices to Peppol does require an API key — see Send to Peppol below.Validate Flags
| Flag | Description |
|---|---|
--json | Machine-readable JSON output |
--quiet | Exit code only, no output |
--version | Show version number |
--help | Show help |
Convert to UBL XML
Convert a getpeppr JSON invoice to Peppol BIS 3.0 UBL 2.1 XML. Credit notes ("isCreditNote": true) are detected automatically and produce the correct UBL CreditNote document.
# Print UBL XML to stdout
getpeppr convert invoice.json
# Write to file
getpeppr convert invoice.json -o invoice.xml
# Validate before converting (errors block conversion)
getpeppr convert invoice.json --validate -o invoice.xml| Flag | Description |
|---|---|
-o, --output <file> | Write XML to file instead of stdout |
--validate | Validate before converting — errors block conversion |
Lookup the Peppol Directory
Search the public Peppol Directory to verify any participant on the network — by Peppol ID or company name.
# Direct lookup by Peppol ID
getpeppr lookup 0208:0685660237
# Search by company name
getpeppr lookup --name "Dupont"
# Filter by country
getpeppr lookup --name "GmbH" --country DE
# JSON output for tooling
getpeppr lookup 0208:0685660237 --json| Flag | Description |
|---|---|
--name <name> | Search by company name (min 3 characters) |
--country <code> | Filter by ISO 2-letter country code |
--json | Output results as JSON |
--limit <n> | Max results for search (default 10) |
Exit Codes
| Code | Meaning |
|---|---|
0 | Pre-flight completed without blocking findings (may have warnings) |
1 | Pre-flight found blocking errors |
2 | File not found or invalid JSON |
JSON Output
Use --json for machine-readable output, ideal for CI pipelines and tooling.
getpeppr validate invoice.json --json{
"structure": { "errors": [], "warnings": [...] },
"schematron": { "errors": [], "warnings": [] },
"countryRules": { "errors": [], "warnings": [...] },
"totalErrors": 0,
"totalWarnings": 2,
"valid": true
}CI/CD Integration
Use --quiet in CI pipelines to gate deployments on invoice compliance.
# Fail the pipeline if the invoice is invalid
getpeppr validate invoice.json --quiet || exit 1
# Or validate multiple files
for file in invoices/*.json; do
getpeppr validate "$file" --quiet || exit 1
done
# Send via API key in env (no login state needed)
GETPEPPR_API_KEY=$SANDBOX_KEY getpeppr send invoice.json --json--quiet flag suppresses all output and relies only on exit codes. It takes precedence over --json, so use one or the other: --json alone in CI to capture structured results, --quiet alone when only the exit code matters.Invoice Format
The input file must be a JSON object matching the InvoiceInput type. See the Type Definitions for all available fields.
{
"number": "INV-2026-001",
"date": "2026-04-07",
"dueDate": "2026-05-07",
"currency": "EUR",
"buyerReference": "PO-12345",
"to": {
"name": "SPF Economie (test receiver)",
"peppolId": "9925:BE0314595348",
"street": "Rue du Progrès 50",
"city": "Brussels",
"postalCode": "1210",
"country": "BE"
},
"lines": [
{
"description": "Consulting services",
"quantity": 10,
"unitPrice": 150,
"vatRate": 0,
"vatCategory": "O",
"taxExemptReason": "Integration test"
}
]
}Send to Peppol
When your invoice JSON is ready, send it through the getpeppr API to the Peppol network — straight from the terminal. Sandbox is the default; pass --prod for production.
getpeppr login — Save your API key
Stores a getpeppr API key in $XDG_CONFIG_HOME/getpeppr/credentials.json — ~/.config/getpeppr/credentials.json by default, %APPDATA%\getpeppr\credentials.json on Windows. On Unix-like systems the file is created and checked with mode 0600; Windows has no POSIX mode, so there the file relies on your account's own permissions. Sandbox and live keys can coexist — the CLI picks the right one based on the target environment.
# Interactive (recommended) — masked input
getpeppr login
# Explicit (required in CI / non-TTY)
getpeppr login --key sk_sandbox_... --sandbox
getpeppr login --key sk_live_... --live| Flag | Description |
|---|---|
--key <key> | API key. CI use only — visible in ps/shell history. Prefer the prompt or GETPEPPR_API_KEY. |
--sandbox | Store as sandbox key (default) |
--live | Store as live (production) key |
--key flag → GETPEPPR_API_KEY env var → stored credentials. In CI, prefer the env var pattern over login --key to avoid leaking the key into shell history.getpeppr send — Send an invoice
Sends an invoice through the getpeppr API to the Peppol network. Pass either a JSON file or the synth flags (--to, --amount, --desc) — they're mutually exclusive.
getpeppr send runs a JSON preflight aligned with POST /v1/invoices. That endpoint currently ignores invoiceTypeCode and lets the provider generate the UBL, so the send preflight does not apply P0100, P0101, or P0112 to that inert field. Structure checks including BR-CL-01, plus every other applicable offline and country check, remain active. Use getpeppr validate or convert --validate for full local-UBL semantics; both retain those profile checks because they validate or build the UBL locally.# Send a JSON file (sandbox by default)
getpeppr send invoice.json
# Watch delivery status until terminal (60s timeout)
getpeppr send invoice.json --watch
# Production send — confirmation prompt (skip with -y)
getpeppr send invoice.json --prod
# Quick test — synthesize from flags using the SPF Economie recipient test ID
getpeppr send --to 9925:BE0314595348 --amount 100 --desc "Test invoice"| Flag | Description |
|---|---|
[file] | Path to invoice JSON (mutex with --to/--amount/...) |
--prod | Target production (uses live key + confirmation prompt) |
--local | Target http://localhost:3001 (dev server) |
--key <key> | Override stored API key |
--to <peppol-id> | Recipient Peppol ID (when no file) |
--country <iso> | Recipient ISO 3166-1 alpha-2 country override (e.g. BE) |
--amount <number> | Line amount in major currency units |
--currency <iso> | ISO 4217 code (default EUR) |
--desc <text> | Line description |
--attachment | Attach the bundled test PDF |
--watch | Poll status until terminal (60s timeout, measured to the start of the last poll). Exits 1 on rejected, failed, no_action (not deliverable), and — since CLI 0.7.0 — whenever the polling itself fails, whether the API answered something unreadable or the request never landed at all. A plain timeout still exits 0 |
-y, --yes | Skip the --prod confirmation prompt |
--no-validate | Skip the JSON send preflight |
--json | Machine-readable JSON output |
--quiet | Exit code only, no output |
getpeppr whoami — Show your Peppol identity
Shows the Peppol identity of the account behind your API key — the quick sanity check that you are pointing at the right account and environment before sending.
# Which account and environment am I pointing at?
getpeppr whoami
# Machine-readable output (carries the full identity — see the note below)
getpeppr whoami --json| Flag | Description |
|---|---|
--prod | Use the live API key (default: sandbox) |
--local | Target http://localhost:3001 (dev server) |
--key <key> | Override stored API key — for CI/scripted use only; visible in ps and shell history, prefer GETPEPPR_API_KEY |
--json | Output the identity as JSON |
--json prints the full identity, including the legal entity name and address — keep it out of shared CI logs and support tickets.
getpeppr logout — Remove credentials
Removes the credentials file described under login. No-op if it doesn't exist.
getpeppr logoutNext Steps
Need a programmatic API instead of the terminal? Use the SDK. Sign up at getpeppr.dev to get your API key.