Nicht verfügbar

Webhooks

Geplant: Echtzeit-Benachrichtigungen über Events in deinem Account. Diese Seite beschreibt den vorgesehenen Vertrag — Events, Payload, Signatur und Retry-Verhalten —, damit eine Integration vorbereitet werden kann.

Webhooks gibt es noch nicht: keiner der 81 Pfade der API-Spezifikation nimmt eine Webhook-Registrierung an. Ein Termin ist nicht gesetzt — sobald einer steht, trägt ihn lib/product-status.ts. Diese Seite ist eine Vorschau auf den geplanten Vertrag, keine Zusage.

Echtzeit-Events

Vorgesehen: sofortige Benachrichtigung bei Rechnungs-Erstellung, Validierung und Konvertierung

Signiert

HMAC-SHA256 Signaturen zum Verifizieren der Authentizität

Automatische Retries

Vorgesehen: Bei Fehlern werden Webhooks automatisch erneut gesendet

Verfügbare Events

EventBeschreibungAuslöser
invoice.createdEine neue Rechnung wurde erfolgreich erstelltPOST /api/v1/invoice/de/xrechnung/generate erfolgreich
invoice.validatedEine Rechnung wurde geprüft und ist konformPOST /api/v1/invoice/{countryCode}/validate liefert `valid: true`
invoice.validation_failedValidierung einer Rechnung ist fehlgeschlagenE-Rechnung entspricht nicht dem Schema
conversion.completedFormat-Konvertierung abgeschlossenPOST /api/v1/invoice/convert erfolgreich
conversion.failedFormat-Konvertierung fehlgeschlagenKonvertierungsfehler
peppol.sentE-Rechnung über Peppol versendetPeppol-Übertragung erfolgreich
peppol.deliveredEmpfangsbestätigung von Peppol erhaltenMDN vom Empfänger
peppol.failedPeppol-Übertragung fehlgeschlagenÜbertragungsfehler

Webhook Payload

Vorgesehenes Format: HTTP POST mit JSON-Body. Die Feldnamen entsprechen dem Rechnungsschema (`subtotal`, `total`, `taxSummary`) und der Generate-Antwort (`format`, `filename`, `mimeType`, `hash`):

json
1{
2 "id": "evt_abc123xyz",
3 "type": "invoice.created",
4 "created": "2026-03-01T10:30:00Z",
5 "data": {
6 "object": {
7 "invoiceNumber": "RE-2026-0042",
8 "format": "xrechnung",
9 "filename": "RE-2026-0042.xml",
10 "mimeType": "application/xml",
11 "hash": "9f2c1b7d4e8a03f5c6b9d0e1a2f3c4b5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1",
12 "currency": "EUR",
13 "subtotal": 1500.00,
14 "total": 1785.00,
15 "taxSummary": [
16 { "taxRate": 19, "taxCategoryCode": "S", "netAmount": 1500.00, "taxAmount": 285.00 }
17 ]
18 }
19 }
20}

HTTP Headers

X-Xhub-Signature

HMAC-SHA256 Signatur des Payloads

X-Xhub-Event

Event-Typ (z.B. invoice.created)

X-Xhub-Delivery

Eindeutige Delivery-ID

X-Xhub-Timestamp

Unix-Timestamp der Signatur-Erstellung

Signatur-Verifizierung

Vorgesehen: Verifiziere die Signatur, um sicherzustellen, dass der Webhook von Invoice-api.xhub stammt:

Node.js / Express

typescript
1import crypto from 'crypto';
2 
3function verifyWebhookSignature(payload, signature, secret) {
4 const expectedSignature = crypto
5 .createHmac('sha256', secret)
6 .update(payload)
7 .digest('hex');
8 
9 const trusted = Buffer.from(`sha256=${expectedSignature}`, 'ascii');
10 const untrusted = Buffer.from(signature, 'ascii');
11 
12 return crypto.timingSafeEqual(trusted, untrusted);
13}
14 
15// Express.js Handler
16app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
17 const signature = req.headers['x-xhub-signature'];
18 const payload = req.body;
19 
20 if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) {
21 return res.status(401).send('Invalid signature');
22 }
23 
24 const event = JSON.parse(payload);
25 
26 switch (event.type) {
27 case 'invoice.created':
28 console.log('Invoice created:', event.data.object.invoiceNumber);
29 break;
30 case 'invoice.validation_failed':
31 console.log('Validation failed:', event.data.object.errors);
32 break;
33 }
34 
35 res.status(200).send('OK');
36});

Python / Flask

python
1import hmac
2import hashlib
3from flask import Flask, request, abort
4 
5app = Flask(__name__)
6WEBHOOK_SECRET = 'your_webhook_secret'
7 
8def verify_signature(payload, signature, secret):
9 expected = hmac.new(
10 secret.encode(),
11 payload,
12 hashlib.sha256
13 ).hexdigest()
14 return hmac.compare_digest(f'sha256={expected}', signature)
15 
16@app.route('/webhook', methods=['POST'])
17def webhook():
18 signature = request.headers.get('X-Xhub-Signature')
19 payload = request.data
20 
21 if not verify_signature(payload, signature, WEBHOOK_SECRET):
22 abort(401)
23 
24 event = request.json
25 
26 if event['type'] == 'invoice.created':
27 print(f"Invoice created: {event['data']['object']['invoiceNumber']}")
28 elif event['type'] == 'invoice.validation_failed':
29 print(f"Validation failed: {event['data']['object']['errors']}")
30 
31 return 'OK', 200

Retry-Policy

Vorgesehen: Wenn dein Endpoint nicht mit 2xxantwortet, soll der Webhook nach diesem Plan erneut gesendet werden:

VersuchWartezeit
1Sofort
21 Minute
35 Minuten
430 Minuten
52 Stunden
612 Stunden

Nach 6 fehlgeschlagenen Versuchen soll der Webhook als fehlgeschlagen markiert und eine E-Mail-Benachrichtigung verschickt werden.

Best Practices

Schnell antworten

Antworte innerhalb von 5 Sekunden mit 200 OK. Verarbeite den Webhook asynchron im Hintergrund.

Signatur verifizieren

Verifiziere immer die HMAC-Signatur. Lehne Requests ohne gültige Signatur ab.

Idempotenz sicherstellen

Speichere die Delivery-ID und verarbeite jeden Webhook nur einmal (Duplikate können bei Retries auftreten).

HTTPS verwenden

Dein Webhook-Endpoint muss HTTPS unterstützen. HTTP-Endpoints werden nicht akzeptiert.

Webhook einrichten

Vorgesehen ist die Konfiguration im Dashboard. Dort soll möglich sein:

  • • Endpoint-URL festlegen
  • • Events auswählen, die gesendet werden sollen
  • • Webhook-Secret einsehen und rotieren
  • • Delivery-Logs und fehlgeschlagene Webhooks einsehen