Naar inhoud

Developer API

Facturen pushen zonder factuurmodule te bouwen.

Gebruik één HTTP API voor facturen, klanten, PDF-statussen en usage events. Je eigen SaaS blijft leidend; Factuurhub verwerkt nummering, branding, PDF’s en team-isolatie.

POST /api/v1/invoices 201 Created
{
  "data": {
    "id": "01jz...invoice",
    "invoice_number": "HOST-2026-000001",
    "status": "finalized",
    "currency": "EUR",
    "subtotal_cents": 2500,
    "tax_total_cents": 525,
    "total_cents": 3025,
    "pdf_status": "pending"
  }
}

Bearer tokens

Plain tokens worden één keer getoond en daarna alleen gehasht opgeslagen.

Idempotency

Retries met dezelfde key maken nooit een tweede factuur.

Private PDF’s

Download geeft 202 zolang de PDF nog niet ready is.

Quickstart

Een factuur in één request.

Maak per SaaS-dienst een API token aan, stuur een Bearer token mee en gebruik een Idempotency-Key voor veilige retries vanuit queues, webhooks of cronjobs.

  1. 1 Maak een service app. Bijvoorbeeld met key hosting.
  2. 2 Maak een API token. Met invoices:create en invoices:read.
  3. 3 Stuur de request. Geef de prijs excl. btw in centen en het btw-tarief op.
  4. 4 Retry gerust. Met dezelfde Idempotency-Key.
curl
curl -X POST https://factuurhub.test/api/v1/invoices \
  -H "Authorization: Bearer factuurhub_test_xxxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: inv-host-2026-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "service_app_key": "hosting",
    "external_invoice_id": "HOST-2026-0001",
    "status": "finalized",
    "currency": "EUR",
    "invoice_date": "2026-06-05",
    "customer": {
      "type": "company",
      "company_name": "Voorbeeld BV",
      "email": "klant@example.nl",
      "country": "NL"
    },
    "lines": [{
      "description": "Hostingpakket juni 2026",
      "quantity": "1.0000",
      "unit_price_cents": 2500,
      "vat_rate": "21.00"
    }]
  }'

Endpoints

Klein oppervlak, duidelijke verantwoordelijkheden.

De API doet alleen wat je SaaS nodig heeft: facturen aanmaken, ophalen, betaald markeren, PDF downloaden en usage events loggen.

POST /api/v1/invoices

Maak een factuur aan

Idempotent via header of external_invoice_id. Maakt ook customer, regels, PDF-status en usage event aan.

GET /api/v1/invoices/{uuid}

Haal factuurdetails op

Geeft customer, regels, totalen en PDF-status terug binnen dezelfde service app.

POST /api/v1/invoices/{uuid}/mark-paid

Markeer betaald

Zet paid of partially_paid en logt een usage event.

GET /api/v1/invoices/{uuid}/download

Download PDF

Vereist invoices:download en geeft 202 als de PDF nog niet ready is.

POST /api/v1/usage-events

Log usage

Voor pay-as-you-go events zoals invoice.api_call of invoice.downloaded.

Auth & abilities

Tokens zijn per SaaS-dienst. Plain tokens worden één keer getoond en daarna alleen gehasht opgeslagen.

  • invoices:create
  • invoices:read
  • invoices:mark_paid
  • invoices:download
  • usage:create

Idempotency

Gebruik een Idempotency-Key voor queue retries. Zonder header gebruikt Factuurhub service_app_id + external_invoice_id als natuurlijke deduplicatie.

Duplicate requests verhogen het factuurnummer niet.

Errors

Fouten zijn bewust simpel: statuscode, korte message en waar nodig validatie-errors. Geen secrets of tokens in logs.

401
Token ontbreekt of is ongeldig.
403
Token mist de vereiste ability.
404
Resource bestaat niet binnen deze service app.
409
Idempotency-conflict: zelfde key, andere payload.
422
Validatiefout, met veld-errors in de response.
429
Rate limit bereikt: 120 requests per minuut per token.

Voorbeelden

Gebruik de API vanuit elke stack.

Geen SDK nodig. Stuur een Bearer token mee, gebruik een vaste Idempotency-Key per factuur en laat Factuurhub de btw en totalen per regel berekenen.

curl -X POST https://factuurhub.test/api/v1/invoices \
  -H "Authorization: Bearer factuurhub_test_xxxxxxxxxxxxxxxxx" \
  -H "Idempotency-Key: inv-host-2026-0001" \
  -H "Content-Type: application/json" \
  -d '{
    "service_app_key": "hosting",
    "external_invoice_id": "HOST-2026-0001",
    "currency": "EUR",
    "invoice_date": "2026-06-05",
    "customer": {
      "type": "company",
      "email": "klant@example.nl",
      "country": "NL"
    },
    "lines": [{
      "description": "Hostingpakket juni 2026",
      "quantity": "1.0000",
      "unit_price_cents": 2500,
      "vat_rate": "21.00"
    }]
  }'
$payload = [
    'service_app_key' => 'hosting',
    'external_invoice_id' => 'HOST-2026-0001',
    'currency' => 'EUR',
    'invoice_date' => '2026-06-05',
    'customer' => [
        'type' => 'company',
        'email' => 'klant@example.nl',
        'country' => 'NL',
    ],
    'lines' => [[
        'description' => 'Hostingpakket juni 2026',
        'quantity' => '1.0000',
        'unit_price_cents' => 2500,
        'vat_rate' => '21.00',
    ]],
];

$ch = curl_init('https://factuurhub.test/api/v1/invoices');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer factuurhub_test_xxxxxxxxxxxxxxxxx',
        'Idempotency-Key: inv-host-2026-0001',
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode($payload),
]);

$response = curl_exec($ch);
Http::withToken(config('services.factuurhub.token'))
    ->withHeaders([
        'Idempotency-Key' => 'invoice-'.$invoice->uuid,
    ])
    ->post('https://factuurhub.test/api/v1/invoices', [
        'service_app_key' => 'hosting',
        'external_invoice_id' => $invoice->number,
        'currency' => 'EUR',
        'invoice_date' => now()->toDateString(),
        'customer' => [
            'type' => 'company',
            'email' => $customer->email,
            'country' => 'NL',
        ],
        'lines' => $lines,
    ])
    ->throw();
import requests

payload = {
    "service_app_key": "hosting",
    "external_invoice_id": "HOST-2026-0001",
    "currency": "EUR",
    "invoice_date": "2026-06-05",
    "customer": {
        "type": "company",
        "email": "klant@example.nl",
        "country": "NL",
    },
    "lines": [{
        "description": "Hostingpakket juni 2026",
        "quantity": "1.0000",
        "unit_price_cents": 2500,
        "vat_rate": "21.00",
    }],
}

response = requests.post(
    "https://factuurhub.test/api/v1/invoices",
    headers={
        "Authorization": "Bearer factuurhub_test_xxxxxxxxxxxxxxxxx",
        "Idempotency-Key": "inv-host-2026-0001",
    },
    json=payload,
    timeout=10,
)

response.raise_for_status()

Koppel je eerste SaaS-dienst.

Begin met één service app, één token en één factuurflow. De rest kan later op dezelfde API mee.