Webhooks
Asynchrone Events von buchkram zu deiner App.
Setup
Im Dashboard unter Einstellungen → Webhooks:
- URL eintragen (HTTPS empfohlen)
- Events auswählen (oder
*für alles) - Secret wird automatisch generiert
Payload-Format
POST https://deine-app.example.com/buchkram-webhook
Content-Type: application/json
User-Agent: buchkram-webhook/1.0
X-Buchkram-Event: invoice.paid
X-Buchkram-Signature: sha256=abc123...
X-Buchkram-Delivery: uuid-of-this-delivery
X-Buchkram-Attempt: 1
{
"event": "invoice.paid",
"tenant_id": "uuid-of-tenant",
"created_at": "2026-05-15T10:30:00+00:00",
"data": {
"invoice": { ...invoice-object... }
}
}
Signatur prüfen
HMAC-SHA256 über den exakten Request-Body, geheim mit deinem Webhook-Secret:
// PHP
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_BUCHKRAM_SIGNATURE']; // "sha256=..."
$expected = 'sha256=' . hash_hmac('sha256', $payload, $YOUR_SECRET);
if (! hash_equals($expected, $signature)) {
http_response_code(401); exit;
}
// Node.js
const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
return res.sendStatus(401);
}
Verfügbare Events
invoice.created,invoice.issued,invoice.booked,invoice.cancelled,invoice.paidreceipt.created,receipt.bookedcustomer.created,customer.updatedproject.created,project.updatedtime_entry.createdquote.created,quote.acceptedbank_transaction.imported,bank_transaction.matched*— alle Events
Retry-Verhalten
Bei HTTP-Statuscode außerhalb 2xx wird mit exponentiellem Backoff bis zu 5x retried:
- Versuch 1 → sofort
- Versuch 2 → nach 30 Sekunden
- Versuch 3 → nach 2 Minuten
- Versuch 4 → nach 10 Minuten
- Versuch 5 → nach 30 Minuten
Danach wird der Webhook nach 100 aufeinanderfolgenden Fehlern automatisch deaktiviert.
Test-Ping
Im Webhook-Settings-Screen gibt es einen "Ping"-Button: schickt ein webhook.ping-Event mit Payload {"message": "pong"}, um deine Endpoint-Anbindung zu verifizieren.