Referenz
| Feld | Wert |
|---|---|
| Version | 1 |
| Geprüft | 2026-08-30 |
| Status | Beta |
| OpenAPI | /openapi/public-v1.yaml |
| Basis-URL | https://api.orbinaut.ccl-dev.com |
Diese Seite beschreibt den ausgelieferten Vertrag. Abweichungen gehören zuerst in die OpenAPI-Datei, dann hierher und in den Changelog.
Authentifizierung
Abschnitt betitelt „Authentifizierung“| Eigenschaft | Wert |
|---|---|
| Schema | Authorization: Bearer <key> |
| Key-Präfix | orb_api_ |
| Herkunft | Dashboard Integrationen, nur Owner und Admin |
| Workspace | ausschließlich aus dem Key, kein Query-Parameter |
Ungültige, fehlende, zu lange, widerrufene oder rotierte Keys ergeben
401 / invalid_api_key. Die Fehlermeldung enthält keine Hashes und keine
internen IDs.
| Scope | Endpunkt | Personenbezogene Daten |
|---|---|---|
courses:read |
GET /api/public/v1/courses, GET /api/public/v1/courses/{courseId} |
nein |
bookings:read |
GET /api/public/v1/bookings |
nein |
participants:read |
derselbe Bookings-Endpunkt | participant.name, participant.email |
participants:read ohne bookings:read lässt sich nicht anlegen. Ein Key mit
nur courses:read erhält auf /bookings 403 / missing_scope.
GET /api/public/v1/courses
Abschnitt betitelt „GET /api/public/v1/courses“Liefert veröffentlichte Kursdurchführungen (courseRun) mit geplanten
Sitzungen des Key-Workspaces, sortiert nach dem frühesten Sitzungsbeginn.
Query: pageSize (1–50, Standard 50), cursor (undurchsichtig, von
nextCursor). Ohne Cursor beginnt die erste Seite.
Erfolg: 200, Body { "data": Course[], "nextCursor": string | null, "pageSize": number },
Header Cache-Control: private, no-store.
data enthält höchstens pageSize Kurse. Jeder Kurs enthält höchstens
pageSize Termine, früheste zuerst. Weitere Kurse folgen über nextCursor.
Weitere Termine eines Kurses liefert GET /api/public/v1/courses/{courseId}.
Die JSON-Antwort ist zusätzlich auf 256 KiB begrenzt.
| Feld | Typ | Bedeutung |
|---|---|---|
id |
string | ID der Kursdurchführung |
title |
string | Titel der Kursvorlage |
description |
string | Beschreibung der Kursvorlage |
audience |
string | Zielgruppe der Kursvorlage |
offeringKind |
string | series oder coaching |
priceInCents |
integer | Preis in Cent, 0 ist kostenlos |
capacity |
integer | Plätze der Durchführung |
waitlistEnabled |
boolean | Warteliste für diese Durchführung |
sessions |
Session[] |
geplante Termine der aktuellen Seite, höchstens pageSize |
Session
Abschnitt betitelt „Session“| Feld | Typ | Bedeutung |
|---|---|---|
id |
string | Sitzungs-ID |
startsAt |
string (ISO-8601 UTC) | Beginn |
durationMinutes |
integer | Dauer in Minuten |
timeZone |
string | IANA-Zeitzone, zum Beispiel Europe/Berlin |
location |
string | Veranstaltungsort |
deliveryMode |
string | in_person oder online |
Entwürfe, nicht veröffentlichte Durchführungen und abgesagte Sitzungen fehlen. Online-Zugangsdaten gehören nicht zur Antwort.
GET /api/public/v1/courses/{courseId}
Abschnitt betitelt „GET /api/public/v1/courses/{courseId}“Liefert eine veröffentlichte Kursdurchführung des Key-Workspaces. Sitzungen
sind nach Beginn sortiert und mit denselben Query-Parametern pageSize und
cursor paginiert.
Erfolg: 200, Body { "data": Course, "nextCursor": string | null, "pageSize": number }.
data.sessions enthält die aktuelle Sitzungsseite. Unbekannte,
unveröffentlichte oder zu einem anderen Workspace gehörende IDs ergeben
404 / course_not_found. Ungültiger Cursor oder unzulässige Seitengröße
ergeben 400 / invalid_pagination.
GET /api/public/v1/bookings
Abschnitt betitelt „GET /api/public/v1/bookings“Liefert Buchungen des Key-Workspaces, neueste zuerst, festes Limit 100. Es gibt keine Cursor-Pagination und keine Filter-Query-Parameter.
Erfolg: 200, Body { "data": Booking[] }, Header
Cache-Control: private, no-store.
Booking
Abschnitt betitelt „Booking“| Feld | Typ | Bedeutung |
|---|---|---|
id |
string | Buchungs-ID |
courseRunId |
string | zugehörige Kursdurchführung |
source |
string | admin, public_page, widget oder api |
status |
string | pending, confirmed, waitlisted, cancelled oder expired |
createdAt |
string (ISO-8601 UTC) | Anlage |
updatedAt |
string (ISO-8601 UTC) | letzte Änderung |
participant |
object, optional | nur mit Scope participants:read |
participant
Abschnitt betitelt „participant“| Feld | Typ | Bedeutung |
|---|---|---|
name |
string | Name der teilnehmenden Person |
email |
string | E-Mail-Adresse |
Ohne participants:read fehlt das Feld participant vollständig. Es wird
nicht als null geliefert.
Jede Fehlerantwort hat diese Form:
{ "error": { "code": "invalid_api_key", "message": "A valid API key is required" }}| HTTP | error.code |
Wann |
|---|---|---|
400 |
invalid_pagination |
Cursor ungültig oder pageSize außerhalb des Bereichs 1–50 |
401 |
invalid_api_key |
Header fehlt, Key ungültig, widerrufen oder rotiert |
403 |
missing_scope |
Key gültig, Scope für den Endpunkt fehlt |
403 |
capability_not_in_plan |
Key gültig, aber der Plan des Workspace enthält die Entwickler-API nicht |
404 |
course_not_found |
Kurs-ID unbekannt, unveröffentlicht oder fremder Workspace |
405 |
method_not_allowed |
andere Methode als GET auf /api/public/v1/ |
429 |
rate_limit_exceeded |
mehr als 120 Anfragen in 60 Sekunden |
Bei 429 setzt die API den Header Retry-After: 60. Clients sollen so viele
Sekunden warten, bevor sie erneut senden.
Die beiden 403-Fälle brauchen verschiedene Reaktionen. missing_scope löst
du mit einem Key, der den fehlenden Scope enthält. capability_not_in_plan
bleibt bestehen, bis der Workspace auf einen Plan mit Entwickler-API wechselt;
ein neuer Key hilft nicht. Siehe
Plan und Abrechnung.
Limits und Caching
Abschnitt betitelt „Limits und Caching“| Limit | Wert |
|---|---|
| Rate-Limit | 120 Anfragen / 60 Sekunden / API-Key |
| Kurs- und Sitzungsseite | 50, Cursor nextCursor, Query pageSize und cursor |
| JSON-Antwort Kurse | höchstens 256 KiB |
| Bookings-Seite | 100, ohne Cursor |
| Cache | Cache-Control: private, no-store |
| Methoden | nur GET; andere Methoden liefern 405 |
Das Rate-Limit ist von Auth-, Widget- und Widget-Analytics-Limits getrennt. Es gibt keine schreibenden öffentlichen REST-Endpunkte in Version 1.
Nicht Teil dieses Vertrags
Abschnitt betitelt „Nicht Teil dieses Vertrags“- Widget-API unter
/api/widget/v1/ - Dashboard-tRPC
- Google-Kalender-Synchronisation (Roadmap)
- native Zapier-App (Roadmap; signierte Webhooks sind der v1-Weg)
Kalenderfeed und Webhooks stehen in Webhooks und Kalender.

