Erstellen Sie einen Endpunkt
Unter Einstellungen → Webhooks fügen Sie die URL hinzu, an die die Ereignisse gesendet werden sollen. Sie erhalten ein Geheimnis zurück — es wird zur Überprüfung der Signatur verwendet und sollte wie ein Passwort gespeichert werden.
Ein System kann sich auch selbst mit einem API-Schlüssel anmelden, ohne dass jemand das Dashboard öffnet. Das ist, wie eine Integration, die Sie nicht selbst geschrieben haben, sich verbindet: Sie erhalten Ihren Schlüssel und registriert ihre eigene Adresse.
| Methode | Pfad | Aktion |
|---|---|---|
| GET | /v1/api/webhooks | Listet Ihre Endpunkte auf |
| POST | /v1/api/webhooks | Erstellt einen und gibt das Geheimnis zurück |
| PATCH | /v1/api/webhooks | Ändert Adresse, Ereignisse oder Status |
| DELETE | /v1/api/webhooks/{id} | Löscht es |
curl -X POST https://api.kuvert.dk/v1/api/webhooks \
-H "Authorization: Bearer pk_live_..." \
-H "Content-Type: application/json" \
-d '{"url":"https://dit-system.dk/kuvert","events":["giftcard.redeemed"]}'Ereignisse
| Ereignis | Wird gesendet, wenn |
|---|---|
| giftcard.issued | Ein Gutschein wird ausgestellt. |
| giftcard.redeemed | Ein Betrag wird von einer Karte abgezogen. |
| order.paid | Eine Bestellung wird bezahlt. |
| order.refunded | Eine Bestellung wird erstattet. |
| ticket.issued | Ein Ticket wird von einer bezahlten Bestellung ausgestellt. |
| order.disputed | Der Kartenaussteller des Käufers hat die Zahlung bestritten. Die Gutscheine und Tickets der Bestellung werden unterbrochen und können nicht verwendet werden. |
| order.dispute_closed | Der Fall ist beendet. `won: true` bedeutet, dass die Unterbrechung aufgehoben ist und die Karten wieder funktionieren; `false` bedeutet, dass sie storniert wurden. |
| booking.created | Ein Tisch wurde gebucht — vom Gast auf der Buchungsseite, am Telefon oder an der Tür. |
| booking.changed | Eine Tischreservierung hat eine neue Uhrzeit, ein neues Datum, eine neue Personenzahl, neue Tische oder einen neuen Status. Die ganze Buchung wird mitgeschickt, und `status` sagt, wo sie steht. |
| booking.cancelled | Eine Tischreservierung wurde storniert, vom Gast oder vom Restaurant. Buchungen, die aus einem anderen System übernommen werden, senden keine Ereignisse. |
Die Signatur
Jede Lieferung trägt einen kuvert-signature-Header mit einem Zeitstempel und einem HMAC:
kuvert-signature: t=1753440000,v1=6f3a…Die Signatur ist HMAC-SHA256 in Hex über den String Zeitstempel, Punkt, Raw Body — berechnet mit Ihrem Endpoint-Geheimnis:
HMAC_SHA256(secret, "{t}.{raw body}")Überprüfung in Node
import { createHmac, timingSafeEqual } from 'node:crypto'
function verify(header, rawBody, secret, toleranceSec = 300) {
const parts = Object.fromEntries(
header.split(',').map((kv) => kv.split('=')),
)
const t = Number(parts.t)
if (!t || !parts.v1) return false
// Afvis for gamle leverancer — det stopper genafspilning.
if (Math.abs(Date.now() / 1000 - t) > toleranceSec) return false
const expected = createHmac('sha256', secret)
.update(`${t}.${rawBody}`)
.digest('hex')
const a = Buffer.from(expected, 'hex')
const b = Buffer.from(parts.v1, 'hex')
return a.length === b.length && timingSafeEqual(a, b)
}Schnell antworten
- Bestätigen Sie mit 2xx, sobald Sie erhalten haben. Legen Sie die schwere Arbeit in eine Warteschlange.
- Lieferung ist Best Effort — ein nicht erreichbarer Endpunkt verzögert niemals einen Kauf.
- Rechnen Sie damit, das gleiche Ereignis zweimal zu erhalten, und machen Sie Ihre Verarbeitung idempotent.
Anforderungen an die URL
Der Endpunkt muss eine öffentlich zugängliche HTTPS-Adresse sein. Interne Adressen werden abgelehnt — dies ist ein bewusster Schutz davor, dass ein Endpunkt dazu verwendet wird, um in unser internes Netzwerk vorzudringen.