Webhooks und Kalender
Neben der lesenden REST-API stellen Integrationen einen Kalenderfeed und ausgehende Webhooks bereit. Beides wird unter Integrationen von Owner und Admin verwaltet. Der Stand ist Beta.
Kalenderfeed
Abschnitt betitelt „Kalenderfeed“Owner und Admins erzeugen eine einmalig sichtbare URL:
https://api.orbinaut.ccl-dev.com/api/calendar/v1/YOUR_CALENDAR_TOKEN.icsDer Token beginnt mit orb_cal_. Die URL ist mit Google Calendar, Apple
Calendar und Outlook abonnierbar. Sie enthält nur veröffentlichte, geplante
Kurstermine des Workspaces.
| Enthalten | Nicht enthalten |
|---|---|
| Kurs-Titel, Beschreibung, Ort | Buchungen |
Beginn, Ende, Zeitzone über DTSTART/DTEND |
Teilnehmername und E-Mail |
text/calendar; charset=utf-8 |
interne Online-Zugangsdaten |
Antworten setzen Cache-Control: private, no-store und
Content-Disposition: inline; filename="orbinaut-calendar.ics". Unbekannte,
widerrufene oder rotierte Tokens sowie Pfade ohne .ics liefern 404 /
calendar_not_found.
Der Feed ist kein REST-JSON-Endpunkt und steht nicht in
public-v1.yaml. Google-Kalender-Synchronisation bleibt Roadmap; v1 liefert
nur den iCal-Export.
Webhook booking.created
Abschnitt betitelt „Webhook booking.created“Jede persistierte Buchung erzeugt für jeden aktiven HTTPS-Endpunkt, der
booking.created abonniert, einen Outbox-Datensatz. Es gibt keinen Zustand
mit gespeicherter Buchung ohne zugehöriges Event.
Zustellung
Abschnitt betitelt „Zustellung“| Eigenschaft | Wert |
|---|---|
| Methode | POST |
| Content-Type | application/json |
| User-Agent | Orbinaut-Webhooks/1.0 |
| Timeout | 10 Sekunden |
| Versuche | höchstens 8 |
| Ziel | nur HTTPS; keine Benutzerdaten in der URL, kein localhost, keine privaten Netze |
Fehlgeschlagene Zustellungen werden mit exponentiellem Backoff wiederholt.
Alle Versuche desselben Events verwenden dieselbe x-orbinaut-event-id und
denselben Body. Empfänger müssen anhand dieser ID idempotent verarbeiten.
| Header | Bedeutung |
|---|---|
x-orbinaut-event-id |
stabile Idempotenz-ID |
x-orbinaut-timestamp |
Unix-Zeit in Sekunden |
x-orbinaut-signature |
v1=<hex-hmac> |
Die Signatur ist HMAC-SHA256(secret, "<timestamp>.<raw-body>"). Empfänger
prüfen den Timestamp gegen ein enges Zeitfenster, berechnen die Signatur über
den unveränderten Request-Body und vergleichen sie in konstanter Zeit.
Das Signing-Secret beginnt mit whsec_ und ist nur einmal sichtbar.
Payload ohne Teilnehmer-Scope
Abschnitt betitelt „Payload ohne Teilnehmer-Scope“{ "id": "event-…", "type": "booking.created", "occurredAt": "2026-08-17T12:00:00.000Z", "data": { "booking": { "id": "booking-…", "source": "widget", "status": "confirmed" }, "course": { "id": "course-…", "title": "Aquarellkurs" } }}Nur der explizite Webhook-Scope participants:read ergänzt
data.participant um name und email. Ohne diesen Scope fehlt das Objekt.
Verifikation (Skizze)
Abschnitt betitelt „Verifikation (Skizze)“import { createHmac, timingSafeEqual } from "node:crypto";
function verifyOrbinautSignature(secret, timestamp, rawBody, header) { const expected = `v1=${createHmac("sha256", secret) .update(`${timestamp}.${rawBody}`, "utf8") .digest("hex")}`; const a = Buffer.from(header); const b = Buffer.from(expected); return a.length === b.length && timingSafeEqual(a, b);}secret, YOUR_API_KEY und echte Zustell-URLs gehören nicht in diese
Dokumentation. Zum Testen einen eigenen HTTPS-Empfänger verwenden, der nicht
in ein privates Netz auflöst.
Eine native Zapier-App ist Roadmap. v1 liefert Zapier-kompatible, signierte Webhook-Events, keine Provider-Synchronisation.
Die REST-Endpunkte bleiben in der Referenz.

