For developers and integration teams

Keep your billing system. Connect its invoices to Peppol.

Create invoices from structured data, send existing invoices and credit notes through Peppol, and retrieve delivery status and received documents. The public REST API works within one OrdoGrid company per key. Your team builds and operates the connection; the reference describes the supported requests and responses.

Choose the integration around your actual workflow

An ERP or your own billing application

Create customers, invoices and credit notes from mapped fields. Keep your source identifier so retries can recover the same document instead of issuing another invoice.

A system that already renders PDFs

Supply the structured invoice fields and optionally your PDF rendering. OrdoGrid builds the UBL from those fields; it does not extract invoice data from a PDF through this API.

An incoming-invoice or reconciliation workflow

Read the Peppol inbox, retrieve exchanged XML and PDF files, and reconcile the results with your system. The company must receive through OrdoGrid for its inbox to fill.

From your source record to an observable result

  1. Create a scoped company key

    An owner or administrator creates a key in Company → API keys. Choose a stable Integration ID and only the required permissions. Start with GET /api/v1/me to confirm the company, integration namespace and effective scopes.

  2. Create and verify the invoice

    POST /api/v1/invoices accepts a stored client_id or an inline client and structured invoice lines. Keep the returned id and assigned number. Omit number to use the company sequence; check the amounts, customer and VAT treatment before transmission.

  3. Check the recipient, then send

    Check GET /api/v1/peppol/participants/{vat_number}, then POST /api/v1/peppol/invoices/{id}/send. Creation needs invoices:write; transmission needs peppol:send. Credit notes have their own credit-notes send route.

  4. Read delivery and retain the exchanged files

    Use GET /api/v1/peppol/invoices/{id}/status with peppol:read. Store document_id and peppol_document_id; use the latter to retrieve the exchanged XML. Submission to the access point, network delivery, the buyer’s response and payment are separate outcomes.

Three separate requests, one invoice

Illustrative HTTP requests, not an interactive console. Replace every placeholder with your own company key, existing client ID and stable operation keys. Use the returned invoice id for send and status. The invoice below has two units at €150 net and 21% VAT; choose the treatment appropriate to your real transaction.

Requests act on real company data. Creating an invoice commits a real record and number. There is no sandbox; send only genuine invoices to an agreed recipient. No request is executed by this page.

1. Create the invoice

POST /api/v1/invoices
Authorization: Bearer <company-api-key>
Idempotency-Key: <stable-create-operation-key>
Content-Type: application/json

{
  "external_id": "your-source-order-id",
  "client_id": "<existing-client-id>",
  "currency": "EUR",
  "items": [
    {
      "description": "Consulting service",
      "quantity": "2",
      "unit_price": "150.00",
      "vat_rate": 21
    }
  ]
}

2. Send the verified invoice

POST /api/v1/peppol/invoices/<invoice-id>/send
Authorization: Bearer <company-api-key>
Idempotency-Key: <stable-send-operation-key>
Content-Type: application/json

{ "include_pdf": true }

3. Read its Peppol status

GET /api/v1/peppol/invoices/<invoice-id>/status
Authorization: Bearer <company-api-key>

The create response carries id and number. The send/status resources use document_id for the invoice and peppol_document_id for its exchanged Peppol document, with normalized status, lifecycle and transmission_state. A successful send response does not prove that the buyer has accepted or paid.

Explore the API reference

Keep control of the company and permissions

  • The key identifies one company; there is no caller-selected company header. App session cookies do not authenticate public API business operations.
  • Grant invoices:write, peppol:send and peppol:read for this example. A write scope includes read on the same resource; peppol:send does not include peppol:read.
  • Copy the secret once into your server-side secret store. Keep it out of browser code, URLs, analytics and logs. Rotate or revoke it from the app when needed.
  • Keep the same Integration ID when replacing a key. Rotation retains it; a newly created key needs the original namespace explicitly supplied.

Build recovery into the connection

Use two identities for retries

On supported POST routes, Idempotency-Key replays a successful response for 24 hours within the same API key. A stable external_id protects document creation within the company, Integration ID and document type beyond that window. Keep the original request body unchanged.

Reconcile an unknown outcome first

After a timeout, look up the invoice by external_id and read its transmission status. An uncertain send may already be on the network: hold it and reconcile the archived transmission before another send. Do not create a fresh invoice to bypass an error.

Respect rate limits and error codes

Read the per-key rate-limit headers and wait for Retry-After on HTTP 429. Branch on the error code, not prose messages. Use paginated reads with limit and offset to collect all records.

Retrieve and reconcile status

Your integration reads the public status and document endpoints and owns its monitoring. Retain the exchanged XML and verify source totals, delivery and settlement separately. The integration guides describe recovery cases and acceptance checks.

Check these boundaries before choosing the API

  • Structured fields are required. There is no PDF-only extraction endpoint or raw UBL-upload send endpoint in this public API. An optional PDF is the rendering, not the source for UBL generation.
  • Peppol transmission supports invoices and credit notes, not quotes or receipts. Company authorisation and applicable monthly quotas are checked before sending.
  • The one-call POST /api/v1/peppol/send creates a real invoice, even with send: false. That option does not provide a sandbox and still checks Peppol authorisation and quota.
  • The public API has no document-email operation. Record payments only after money has moved through your own payment channel; a payments:write operation does not charge a card or transfer money.
  • A connection needs field mapping, development and operational ownership. This is not a ready-made connector to every ERP or accountant. Existing history and exports need a separate migration plan.

Questions about invoicing through the API

Can I read the documentation without an account?
Yes. The reference and GET /api/v1/openapi.json are public. Business operations require your own company API key and the scopes specified by each operation.
Can I keep the PDFs my system already produces?
Yes. Supply your PDF together with matching structured data, or upload its rendering to the existing invoice. The reference describes the accepted formats. Verify that the rendering and structured amounts agree before sending.
Is the API needed for a few invoices a month?
Usually the app is enough. The free forever plan includes unlimited Peppol receiving and one outgoing invoice per month; Starter adds unlimited sending. Choose Business when you need this API or its other included workflows.
Can I read status with only peppol:send?
No. Add peppol:read for recipient lookups, delivery status, the inbox and exchanged documents. Use the narrowest scopes that cover your integration.

Plan and implement the connection