dokun

Dokun API-Dokumentation

Die Dokun-API dient der Anbindung deiner Kasse (POS) und eigener Systeme. Alle Anfragen nutzen JSON über HTTPS. Basis-URL:

https://dokun.io/api/v1

Paketvoraussetzung

API und Webhooks sind nur im Pro-Paket verfügbar. Das Paket wird bei jeder Anfrage geprüft: Ist die Testphase abgelaufen oder die Zahlung fehlgeschlagen, antworten Anfragen mit 402, in Nicht-Pro-Paketen mit 403; Webhooks werden nicht gesendet.

Authentifizierung

Erstelle einen API-Schlüssel im Dashboard. Schlüssel beginnen mit dk_ und werden nur einmal bei der Erstellung angezeigt (wir speichern nur einen Hash). Sende ihn bei jeder Anfrage im Authorization-Header mit dem Bearer-Schema. Der Schlüssel ist an dein Unternehmen gebunden und greift nur auf eigene Karten zu.

Authorization: Bearer dk_...

Ratenbegrenzung

Höchstens 60 Anfragen pro Minute und Schlüssel. Bei Überschreitung antwortet die API mit 429; der retry-after-Header nennt die Sekunden bis zur nächsten Minute.

Fehlercodes

Fehlerantworten sind Klartext, kein JSON. Werte den Statuscode aus.

CodeBodyWann
400serial gerekli / geçersiz Idempotency-Keyserial fehlt oder Idempotency-Key ungültig
401unauthorizedSchlüssel fehlt oder ungültig
402payment requiredTestphase abgelaufen oder Abo gesperrt
403planPaket enthält keine API (nicht Pro)
404kart bulunamadıKarte nicht gefunden oder gehört einem anderen Unternehmen
409istek işleniyorAnfrage mit gleichem Idempotency-Key läuft noch
429rate limitRatenlimit überschritten

Kunden abrufen

GET /api/v1/customers

Liefert die Kunden deines Unternehmens, neueste zuerst. Es gibt keine Paginierung: Die Antwort enthält höchstens 200 Einträge (die 200 neuesten Anmeldungen). marketing_consent_at ist der Zeitpunkt der Werbeeinwilligung, sonst null.

curl https://dokun.io/api/v1/customers \
  -H "Authorization: Bearer dk_..."

{ "customers": [ { "id": "…", "name": "Ayşe", "email": "ayse@example.com",
  "created_at": "2026-10-30T09:12:00Z", "marketing_consent_at": null } ] }

Stempel buchen

POST /api/v1/stamp

Bucht Stempel auf eine Karte. serial ist die Seriennummer oder der vollständige an der Kasse gescannte QR-Text (unverändert senden). delta ist optional, Standard 1. multiplier in der Antwort ist der durch eine Aktion (z. B. Doppelstempel) angewandte Faktor. Bei Erfolg wird die Karte in Apple Wallet aktualisiert und der stamp-Webhook ausgelöst.

curl -X POST https://dokun.io/api/v1/stamp \
  -H "Authorization: Bearer dk_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: fis-000123" \
  -d '{"serial": "ABC123", "delta": 1}'

{ "ok": true, "balance": 4, "multiplier": 1 }

Idempotency-Key

Für sichere Wiederholungen nach Netzwerkfehlern sende den optionalen Header Idempotency-Key (1–64 druckbare ASCII-Zeichen, z. B. Belegnummer). Derselbe Schlüssel liefert 24 Stunden lang dieselbe Antwort, der Stempel wird nicht wiederholt; eine wiederholte Antwort trägt den Header idempotent-replayed: true. Nur erfolgreiche Antworten werden gespeichert; eine fehlgeschlagene Anfrage kann mit demselben Schlüssel wiederholt werden.

Webhooks

Lege im Dashboard einen Webhook mit HTTPS-URL und Ereignistyp an. Bei jedem Ereignis senden wir einen POST mit JSON-Body an deine URL. Format: event (Ereignisname), data (Ereignisdaten), ts (Unix-Zeit in Millisekunden).

Ereignisdata-FelderWann
signupemail, serialNeue Kartenanmeldung. Enthält personenbezogene Daten (E-Mail); sicher speichern.
stampserial, balanceStempel an der Kasse oder im Dashboard
stampserial, delta, multiplier, balanceStempel über die API
rewardserial, balance, targetPrämie erreicht. Nur bei Kassen-/Dashboard-Stempeln, nicht bei API-Stempeln.
POST https://ornek.com/dokun-webhook
content-type: application/json
x-dokun-signature: 5d41402abc4b2a76…
x-dokun-attempt: 1

{ "event": "stamp", "data": { "serial": "ABC123", "balance": 4 }, "ts": 1761815520000 }

Zustellung und Wiederholungen

Nur eine 2xx-Antwort gilt als Erfolg; Weiterleitungen (3xx) werden nicht verfolgt, Anfragen laufen nach etwa 5 Sekunden ab. Fehlgeschlagene Zustellungen werden mit exponentiellem Backoff (nach etwa 2 und 4 Minuten) bis zu insgesamt 3 Versuchen wiederholt; der Header x-dokun-attempt nennt die Versuchsnummer. Wiederholungen senden denselben Body: nutze event + ts + data gegen Doppelverarbeitung.

Signaturprüfung

Bei jeder Anfrage ist der Header x-dokun-signature der HMAC-SHA256 des rohen Bodys mit deinem Webhook-Secret (der im Dashboard angezeigte Wert, unverändert), hex-kodiert. Prüfe gegen den Rohtext vor dem JSON-Parsing und vergleiche in konstanter Zeit. Die Signatur enthält keinen Zeitstempel; prüfe das Feld ts gegen Replays (z. B. Ereignisse älter als 10 Minuten ablehnen).

import { createHmac, timingSafeEqual } from 'node:crypto'

const raw = await req.text() // JSON.parse'tan önce ham gövde
const expected = createHmac('sha256', process.env.DOKUN_WEBHOOK_SECRET).update(raw).digest()
const got = Buffer.from(req.headers.get('x-dokun-signature') ?? '', 'hex')
if (got.length !== expected.length || !timingSafeEqual(got, expected)) return new Response(null, { status: 401 })
const { event, data, ts } = JSON.parse(raw)
if (Date.now() - ts > 10 * 60_000) return new Response(null, { status: 400 })

Fragen: WhatsApp