> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ouraicalling.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Kalender & Buchung

> Lass Assistenten während des Anrufs die Verfügbarkeit prüfen und Termine buchen – über Acuity Scheduling, Cal.com, Calendly, Google Calendar, Outlook oder die integrierte Buchungs-Engine

Terminplanung ist der klassische Anwendungsfall für einen Voice-Agenten: Der Assistent prüft während des Anrufs freie Termine, bietet ein paar Optionen an und bucht den, für den sich der Anrufer entscheidet. Die Plattform unterstützt das auf zwei Arten, die sich frei kombinieren lassen:

1. **Kalenderintegrationen** – verbinde einmal einen externen Planungsanbieter (Acuity Scheduling, Cal.com, Calendly, Google Calendar, Outlook), weise ihn einem Assistenten zu, und der Assistent bekommt automatisch Buchungstools für jeden Anruf.
2. **Die integrierte Buchungs-Engine** – definiere eigene Event-Typen mit wöchentlicher Verfügbarkeit und erhalte eine öffentliche, einbettbare Buchungsseite unter `/book/{workspace}/{slug}`, ICS-Einladungs-E-Mails und eine `native`-Integration, über die deine Assistenten buchen können. Kein externes Konto nötig.

## Anbieter im Überblick

| Anbieter                       | Verfügbarkeit                                                     | Buchung                                                                                      | Zugangsdaten                                |
| ------------------------------ | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------- |
| **Cal.com**                    | ✓ offene Slots eines Event-Typs                                   | ✓ Direktbuchung                                                                              | API-Key (`cal_…`) + numerische Event-Typ-ID |
| **Calendly**                   | ✓ verfügbare Zeiten eines ausgewählten Event-Typs                 | ✓ Direktbuchung (kostenpflichtige Calendly-Pläne), Einmal-Buchungslink und bestätigte Absage | OAuth-Verbindung (einmalig)                 |
| **Acuity Scheduling**          | ✓ Live-Slots oder Kursverfügbarkeit eines ausgewählten Termintyps | ✓ Direktbuchung, bestätigte Absage und Umbuchung (Serien können nicht verschoben werden)     | OAuth-Verbindung (einmalig)                 |
| **Google Calendar**            | ✓ Frei/Gebucht eines verbundenen Kalenders                        | ✓ Termin-Erstellung mit Teilnehmereinladung                                                  | OAuth-Verbindung (einmalig)                 |
| **Outlook / Microsoft 365**    | ✓ Frei/Gebucht über Microsoft Graph                               | ✓ Termin-Erstellung mit Teilnehmereinladung                                                  | OAuth-Verbindung (einmalig)                 |
| **Nativ (integrierte Engine)** | ✓ berechnet aus der wöchentlichen Verfügbarkeit deines Event-Typs | ✓ Direktbuchung + ICS-E-Mail                                                                 | keine                                       |

<Note>
  **Calendly-Link-Modus**: Die Scheduling-API von Calendly setzt einen kostenpflichtigen Calendly-Plan voraus. Wenn dein Plan nicht direkt buchen kann, setze `booking_mode` der Integration auf `link` – der Assistent einigt sich dann mit dem Anrufer auf einen groben Zeitpunkt und schickt statt einer festen Buchung einen **Einmal-Buchungslink** per SMS oder E-Mail (`link_channel`). Integrationen, die während des Anrufs an diese Plan-Beschränkung stoßen, werden mit dem Status `link_mode` markiert.
</Note>

## Eine Integration verbinden

Gehe zu **Buchung → Integrationen** und wähle eine Anbieter-Karte aus:

* **Cal.com** – füge deinen API-Key ein (Cal.com → Settings → Developer → API Keys) sowie die numerische Event-Typ-ID (sichtbar in der Event-Typ-URL). Optional kannst du die Zeitzone überschreiben – achte darauf, dass sie zum Cal.com-Event-Typ passt.
* **Calendly** – klicke auf **Mit Calendly verbinden**, bestätige den Zugriff und wähle anschließend einen aktiven Event-Typ nach **Name und Dauer** aus. Eine Kontoverbindung kann von mehreren Integrationen verwendet werden; jede Integration wählt genau einen Event-Typ. Lege Buchungsmodus (`api` oder `link`), Link-Kanal sowie Book-/Cancel-Berechtigungen fest. Vollständige Calendly-Ressourcen-URIs und rotierende Refresh-Tokens bleiben intern.
* **Acuity Scheduling** – klicke auf **Mit Acuity verbinden**, bestätige den Zugriff `api-v1` und wähle anschließend einen Termintyp. Optional kannst du einen bestimmten Acuity-Kalender bzw. eine Person auswählen; mit **Beliebiger verfügbarer Kalender** lässt du Acuity jede Buchung einem verfügbaren Kalender zuordnen, der diesen Termintyp anbietet. Book, Cancel und Reschedule lassen sich pro Integration ein- oder ausschalten; bei Serien wird Reschedule deaktiviert, weil Acuity diese im Client-Modus nicht verschiebt. OAuth-Tokens bleiben serverseitig und werden nie von der API ausgegeben.
* **Google / Outlook** – klicke auf **Connect** und schließe die OAuth-Zustimmung ab. Die Verbindung wird pro Workspace gespeichert und von jeder Integration und jedem Event-Typ wiederverwendet, der darauf verweist.
* **Nativ** – wähle einen deiner Buchungs-Event-Typen aus (siehe unten).

Jede Integration wird **vor dem Speichern geprüft**: Ein ungültiger API-Key, eine ungültige OAuth-Verbindung oder Event-Typ-ID wird mit einer klaren Fehlermeldung abgelehnt und nie gespeichert. Geheime Werte verlassen nie den Server – in Antworten werden sie als `•••` maskiert (sende beim Update `•••`, um ein gespeichertes Legacy-Secret beizubehalten).

Wenn die letzte Integration gelöscht wird, die ein Acuity-Konto verwendet, widerruft die Plattform dessen OAuth-Token über Acuitys Disconnect-Endpunkt und entfernt die lokale Verbindung. Ein ungenutztes Konto kann außerdem im Acuity-Editor über **Konto trennen** entfernt werden; gemeinsam verwendete Konten lassen sich erst trennen, nachdem die übrigen Integrationen entfernt wurden.

<Note>
  Für eine selbst verwaltete Calendly-Developer-App trägst du
  `https://www.ouraicalling.de/api/oauth/calendly/callback` als produktive
  **Redirect URI** ein. Aktiviere `users:read`, `event_types:read`,
  `locations:read`, `scheduled_events:write` und `scheduling_links:write`.
  Webhook-Scopes und der Webhook-Signing-Key werden für diese Verbindung nicht
  benötigt.
</Note>

Bestehende Personal-Access-Token-Integrationen funktionieren weiter, erscheinen
aber als **Alte Verbindung – erneut mit Calendly verbinden**. Beim erneuten
Verbinden wird auf OAuth umgestellt und das PAT aus der Integration entfernt.

<Note>
  Registriere für den Acuity-OAuth-Client
  `{OAUTH_REDIRECT_BASE_URL}/api/mcp-connectors/callback` als exakte Redirect-URI.
  Der Callback erkennt Acuity am namespaced, einmalig verwendbaren State, bevor
  der generische MCP-Connector-Handler läuft, und leitet danach zur ursprünglichen
  Workspace-Domain zurück. Konfiguriere `ACUITY_OAUTH_CLIENT_ID` und
  `ACUITY_OAUTH_CLIENT_SECRET`; setze `ACUITY_OAUTH_REDIRECT_URI` nur, wenn eine
  bestimmte registrierte URI fest vorgegeben werden soll. Das Client-Secret darf
  nie in Browser-Code landen. Zum Starten dieses interaktiven OAuth-Flows ist ein
  benutzergebundener Owner-/Admin-Zugang erforderlich; Service-Account-Zugänge
  werden absichtlich abgelehnt.
</Note>

## Einem Assistenten zuweisen

Öffne die Einstellungen des Assistenten und hake die Integrationen ab, die er nutzen soll (oder rufe `PUT /api/v1/assistants/{id}/integrations` auf). Für **jede zugewiesene Integration** bekommt der Assistent bei jedem Anruf diese Tools:

| Tool                                                           | Typ                                                          | Was es macht                                                                                                                                                                                                                |
| -------------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `check_availability(start_date, end_date?)`                    | nur lesend, unterbrechbar                                    | Ruft offene Slots für den Datumsbereich ab und liest sie in der Zeitzone des Assistenten vor (gedeckelt, damit der Agent nie 200 Slots aufzählt).                                                                           |
| `book_appointment(name, email, start, notes?)`                 | schreibend – läuft mit einer Füllphrase, nicht unterbrechbar | Bucht den gewählten Slot. Bei Erfolg werden Buchungsstart und -ID als Call-Variablen für Flows, Analysen und Webhooks gespeichert. War der Slot gerade schon vergeben, wird der Agent angewiesen, einen anderen anzubieten. |
| `send_booking_link(email?, phone?)`                            | nur im Calendly-Link-Modus                                   | Erstellt einen Einmal-Buchungslink und verschickt ihn per SMS oder E-Mail.                                                                                                                                                  |
| `find_appointment(email, name)`                                | Calendly-/Acuity-Verwaltung                                  | Findet kommende Termine des ausgewählten Event-/Termintyps. Exakte Buchungs-E-Mail und vollständiger Name sind erforderlich.                                                                                                |
| `cancel_appointment(event_id / appointment_id, confirmed)`     | schreibend – nicht unterbrechbar                             | Sagt nur einen Termin ab, den `find_appointment` im selben Anruf geliefert hat, nachdem der Assistent ihn vorgelesen und eine ausdrückliche Bestätigung erhalten hat.                                                       |
| `reschedule_appointment(appointment_id, new_start, confirmed)` | Acuity-Verwaltung                                            | Verschiebt nur einen im selben Anruf gefundenen Acuity-Termin, nachdem die Verfügbarkeit geprüft und die neue Zeit ausdrücklich bestätigt wurde.                                                                            |

Ist mehr als eine Integration zugewiesen, bekommen die Tool-Namen den Integrationsnamen als Suffix (zum Beispiel `check_availability_sales`). Slots werden immer in der **Zeitzone des Assistenten** angesagt – stelle sie in den Assistenten-Einstellungen ein.

<Tip>
  Sag dem Assistenten in seinem Prompt, **wann** er buchen soll, z. B.: *„Bevor du eine Zeit anbietest, rufe check\_availability auf. Sobald der Anrufer einen Slot bestätigt, rufe book\_appointment mit Name und E-Mail auf.“*
</Tip>

## Die integrierte Buchungs-Engine

Lege Event-Typen unter **Buchung** im Dashboard an (oder über API/MCP):

* **Name, Slug, Dauer** – der Slug ist innerhalb des Workspace eindeutig und wird zur URL der öffentlichen Seite `/book/{workspace}/{slug}` (`workspace` = Tenant-`booking_handle`).
* **Wöchentliche Verfügbarkeit** – Zeitfenster pro Wochentag in der Zeitzone des Event-Typs, z. B. Mo–Fr 09:00–17:00 Uhr.
* **Puffer & Regeln** – Puffer vor/nach jeder Buchung, Mindestvorlauf, Buchungshorizont (`max_days_ahead`) und Slot-Intervall.
* **Kalender-Sync** (optional) – verknüpfe einen verbundenen Google-/Outlook-Kalender: Seine Belegungszeiten werden von den angebotenen Slots abgezogen, und bestätigte Buchungen werden als Kalendereinträge übertragen (Teilnehmer erhalten die Einladung des Anbieters).

### Öffentliche Buchungsseite & Einbettung

Jeder aktive Event-Typ hat eine öffentliche Seite im Branding deines Tenants unter `https://<your-domain>/book/{workspace}/{slug}` – ohne Login nötig. Bette sie überall ein:

```html theme={null}
<iframe src="https://<your-domain>/book/acme/intro-call"
        style="width:100%;min-height:640px;border:0" loading="lazy"></iframe>
```

Besucher wählen einen Slot (angezeigt in ihrer eigenen Zeitzone), geben Name und E-Mail ein und erhalten eine **Bestätigungs-E-Mail mit ICS-Kalendereinladung** plus einen Stornierungslink. Doppelbuchungen sind ausgeschlossen – ein Exclusion-Constraint auf Datenbankebene schützt den Slot, selbst wenn ein Website-Besucher und ein Assistent im selben Moment buchen; wer den Slot verpasst, bekommt die freundliche Meldung, dass er gerade vergeben wurde.

### Buchung aus Anrufen

Erstelle eine Integration mit dem Anbieter **`native`**, die auf den Event-Typ verweist, und weise sie einem Assistenten zu – Buchungen während des Anrufs landen dann im selben Kalender mit `source: "call"` und einem Link zum Anruf-Datensatz.

## Plan-Gating

Das gesamte Feature wird über das Plan-Flag **`calendar_integrations`** freigeschaltet (Plattform-Admin → Pläne). Ohne dieses Flag liefert das Erstellen von Integrationen oder Event-Typen `403`; bestehende öffentliche Buchungsseiten nehmen keine neuen Buchungen mehr an.

## API & MCP

Alles oben Beschriebene steht über die [öffentliche REST-API](/api-reference/introduction) und als MCP-Tools unter `https://<your-domain>/mcp` zur Verfügung:

`GET /api/v1/bookings` und `list_bookings` unterstützen Filter nach Event-Typ, Quelle und Datum. Verwende `view=upcoming|unconfirmed|recurring|past|cancelled` für dieselben Buchungsansichten wie im Dashboard, oder nutze einen exakten `status`-Filter; `view` und `status` schließen sich gegenseitig aus.

| REST                                                                                        | MCP-Tool                                                                                                         | Scope                                |
| ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------ |
| `GET/POST /api/v1/integrations`, `GET/PATCH/DELETE /api/v1/integrations/{id}`               | `list_integrations`, `get_integration`, `create_integration`, `update_integration`, `delete_integration`         | `integrations:read/write`            |
| `POST /api/v1/integrations/calendly/oauth-url`                                              | `create_calendly_oauth_url`                                                                                      | `integrations:write`                 |
| `GET /api/v1/integrations/calendly/connections`                                             | `list_calendly_connections`                                                                                      | `integrations:read`                  |
| `GET /api/v1/integrations/calendly/event-types?connection_id=…`                             | `list_calendly_event_types`                                                                                      | `integrations:read`                  |
| `POST /api/v1/integrations/acuity/oauth-url`                                                | `create_acuity_oauth_url`                                                                                        | `integrations:write`                 |
| `GET /api/v1/integrations/acuity/connections`                                               | `list_acuity_connections`                                                                                        | `integrations:read`                  |
| `GET /api/v1/integrations/acuity/appointment-types?connection_id=…`                         | `list_acuity_appointment_types`                                                                                  | `integrations:read`                  |
| `GET /api/v1/integrations/acuity/calendars?connection_id=…`                                 | `list_acuity_calendars`                                                                                          | `integrations:read`                  |
| `GET/PUT /api/v1/assistants/{id}/integrations`                                              | `get_assistant_integrations`, `set_assistant_integrations`                                                       | `integrations:*` oder `assistants:*` |
| `GET/POST /api/v1/booking-event-types`, `GET/PATCH/DELETE /api/v1/booking-event-types/{id}` | `get_booking_event_types`, `create_booking_event_type`, `update_booking_event_type`, `delete_booking_event_type` | `bookings:read/write`                |
| `GET /api/v1/bookings`, `GET /api/v1/bookings/{id}`, `POST /api/v1/bookings/{id}/cancel`    | `list_bookings`, `get_booking`, `cancel_booking`                                                                 | `bookings:read/write`                |

Wenn du eine Buchung stornierst, wird ein ICS-Update mit `METHOD:CANCEL` verschickt, sodass der Termin automatisch aus dem Kalender der eingeladenen Person verschwindet.
