Skip to main content

Getting Started

Send your first invoice through the Peppol network in under 5 minutes.

Prerequisites

  • An Invostaq account with a tenant (sign up at invostaq.com)
  • An API key (starts with sk_test_ for sandbox or sk_live_ for production)

Generate an API key from the Invostaq dashboard at Settings > API Keys. See the Authentication guide for details.


Step 1: Look up the recipient

Before sending an invoice, verify the recipient is registered on the Peppol network and get their routing info.

curl https://api.invostaq.com/api/v2/lookup?participantId=0196:971501234567 \
-H "x-api-key: sk_test_dGVzdGtleS0xMjM0NTY3ODkwYWJjZGVm"
{
"participantId": "0196:971501234567",
"isRegistered": true,
"accessPointRef": "AP-0196-971501234567",
"supportedDocTypes": [
"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
],
"provider": "Invostaq"
}

The response tells you:

  • isRegistered — whether the recipient can receive Peppol documents
  • accessPointRef — the routing reference you need in Step 2
  • supportedDocTypes — which document types the recipient accepts

If isRegistered is false, the recipient isn't on the Peppol network yet.


Step 2: Send the invoice

Post your invoice data with the routing information from Step 1. v2 is the recommended contract for new integrations.

curl -X POST https://api.invostaq.com/api/v2/invoices/send \
-H "x-api-key: sk_test_dGVzdGtleS0xMjM0NTY3ODkwYWJjZGVm" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: inv-2024-001-first-attempt" \
-d '{
"invoice": {
"number": "INV-2024-001",
"issueDate": "2024-06-15",
"currency": "EUR",
"supplier": {
"name": "Acme Trading NV",
"taxId": "BE0417497106",
"address": {
"line1": "Rue de la Loi 1",
"city": "Brussels",
"postalCode": "1000",
"countryCode": "BE"
}
},
"buyer": {
"name": "Gulf Imports Co",
"taxId": "971501234567",
"address": {
"line1": "Sheikh Zayed Road",
"city": "Dubai",
"countryCode": "AE"
}
},
"lineItems": [
{
"description": "Consulting services — June 2024",
"quantity": 1,
"unitPrice": 1000.00,
"taxRate": 21.0
}
],
"totals": {
"subtotal": 1000.00,
"taxAmount": 210.00,
"grandTotal": 1210.00
}
},
"routing": {
"senderParticipantId": "0208:0417497106",
"receiverParticipantId": "0196:971501234567",
"accessPointRef": "AP-0196-971501234567"
}
}'
{
"invoiceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"transactionId": "txn_abc123def456",
"status": "success",
"networkStatus": "Processing",
"idempotencyKeyEcho": "inv-2024-001-first-attempt",
"provider": "Invostaq"
}

Your invoice is now being routed through the Peppol network. The initial networkStatus is Processing — it updates to Delivered or Failed once the recipient's Access Point responds.

About the Idempotency-Key: If your request times out or you're unsure whether it succeeded, retry with the same key. The API returns the original result without resubmitting to Peppol. Keys can be any string up to 128 characters — invoice numbers, UUIDs, or any value unique to this submission.

Note on taxRate: Tax rates are specified as percentages. Use 21.0 for 21%, not 0.21.


Step 3: Track delivery via webhooks

Set up a webhook to receive delivery status updates in real time. Register your endpoint from the Invostaq dashboard under Settings > Webhooks.

When the invoice is delivered, you receive:

{
"transactionId": "txn_abc123def456",
"eventType": "transaction.sent",
"status": "Delivered"
}

If delivery fails:

{
"transactionId": "txn_abc123def456",
"eventType": "transaction.failed",
"status": "Failed",
"reason": "Recipient Access Point unreachable"
}

Always respond with 200 OK. See the Webhooks guide for the full event reference and retry behavior.


Common mistakes

MistakeWhat happensFix
Missing x-api-key header401 api-key-requiredAdd your API key to the header
Wrong participant ID format400 invalid-sender-idUse ISO 6523 format: 0196:971501234567
Declared totals inconsistent (v2)400 declared-totals-mismatchgrandTotal must equal subtotal + taxAmount; subtotal must equal sum of line extensions
Line totals don't add up (v1)400 totals-mismatchRecalculate: sum(qty * price + tax) must match totalAmount within ±0.02
No Idempotency-Key on retryDuplicate invoice sentAlways include an idempotency key

What's next

GuideWhen you need it
API OverviewInvoice lifecycle, all endpoints at a glance
AuthenticationKey management, sandbox vs. live, rate limits
ErrorsEvery error type with full JSON examples
WebhooksEvent types, security, retry behavior
curl ExamplesLookup, send, idempotency, error handling
TypeScript ExamplesFull client with retry logic