Zum Inhalt springen
Dokumentation

API

Webhooks

Ein Webhook lässt Kuvert Ihrem System mitteilen, dass etwas passiert ist — eine Karte wurde ausgegeben, ein Betrag wurde belastet, eine Bestellung wurde bezahlt oder erstattet, ein Tisch wurde gebucht oder storniert. Jede Lieferung ist signiert, daher können Sie beweisen, dass sie von uns kam.

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.

MethodePfadAktion
GET/v1/api/webhooksListet Ihre Endpunkte auf
POST/v1/api/webhooksErstellt einen und gibt das Geheimnis zurück
PATCH/v1/api/webhooksÄndert Adresse, Ereignisse oder Status
DELETE/v1/api/webhooks/{id}Löscht es
Terminal
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

EreignisWird gesendet, wenn
giftcard.issuedEin Gutschein wird ausgestellt.
giftcard.redeemedEin Betrag wird von einer Karte abgezogen.
order.paidEine Bestellung wird bezahlt.
order.refundedEine Bestellung wird erstattet.
ticket.issuedEin Ticket wird von einer bezahlten Bestellung ausgestellt.
order.disputedDer Kartenaussteller des Käufers hat die Zahlung bestritten. Die Gutscheine und Tickets der Bestellung werden unterbrochen und können nicht verwendet werden.
order.dispute_closedDer Fall ist beendet. `won: true` bedeutet, dass die Unterbrechung aufgehoben ist und die Karten wieder funktionieren; `false` bedeutet, dass sie storniert wurden.
booking.createdEin Tisch wurde gebucht — vom Gast auf der Buchungsseite, am Telefon oder an der Tür.
booking.changedEine 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.cancelledEine 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

JavaScript
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.