# Veeting Rooms REST APIs

Source: https://www.veeting.com/de/developer-documentation/api-usage

## Übersicht

Mit der Veeting REST API erstellen Sie aus Ihrer eigenen Software heraus Konten, planen Meetings im Namen Ihrer User und verwalten diese Meetings über den ganzen Lebenszyklus. Es ist eine ganz normale JSON-API über HTTPS, Sie können also jeden HTTP-Client einsetzen. Die Beispiele unten verwenden `curl`.

**Basis-URL:** `https://<DOMAIN-NAME>/api/v6`

`<DOMAIN-NAME>` ist Ihre eigene Meeting-Domain. Einen gemeinsamen oder globalen Host gibt es nicht: Nehmen Sie die Domain, unter der Ihre Instanz läuft.

**Authentifizierung:** ein `X-API-KEY`-Header bei jedem Aufruf.

**Content-Type:** `application/json` bei jedem POST und PUT.

## Verwendung mit einem KI-Assistenten

Viele Integrationen entstehen heute mit einem KI-Assistenten. Arbeiten Sie ebenso, dann kopieren Sie den folgenden Text in Ihren Assistenten und schreiben Sie einen Satz dazu, was Sie bauen möchten.

Der Text schickt den Assistenten zuerst auf diese Seite und warnt ihn vor den wenigen Dingen, die er sonst gerne falsch macht.

```text
Lies zuerst diese Seite, bevor Du Code schreibst:
https://www.veeting.com/de/developer-documentation/api-usage

Sie dokumentiert die Veeting Rooms REST API. Halte Dich an diese
fünf Regeln:

1. Frage mich nach meiner Veeting-Domain. Rate nicht.
2. Der API-Key ist ein serverseitiges Geheimnis. Frage ich nach
   einer Browser-Integration, dann baue stattdessen ein Backend
   dafür und sage mir warum.
3. Ein Aufruf war nur dann erfolgreich, wenn der HTTP-Status 200
   ist UND der Body responseCode 0 enthält. Prüfe beides.
4. Ein Meeting hat zwei IDs. Verwende die 24-stellige «id» in
   API-Aufrufen und die «meetingId» mit den Bindestrichen im
   Meeting-Link. Vertausche sie nie.
5. Frage mich, ob mein API-Key auf Kontoebene oder auf
   Instanzebene liegt. Das ändert, welche Endpunkte und Header
   gelten.

Was ich bauen möchte:
```

## Regeln für jeden Aufruf

Diese vier Regeln gelten für jeden Endpunkt auf dieser Seite. Regel 2 überrascht die meisten: Lesen Sie sie auch dann, wenn Sie den Rest überspringen.

1. **Der API-Key ist ein serverseitiges Geheimnis.** Wer ihn hat, steuert Ihre ganze Meeting-Plattform. Legen Sie ihn deshalb nie in Browser-JavaScript, in ein Mobile-App-Bundle oder in ein öffentliches Repository. Wollen Sie Meetings aus dem Browser heraus starten, dann rufen Sie die API von Ihrem eigenen Backend aus auf und geben nur das Ergebnis an die Seite weiter.

2. **Ein erfolgreicher Aufruf liefert HTTP 200 *und* `responseCode: 0`.** Die meisten Endpunkte antworten auch dann mit HTTP 200, wenn der Aufruf fehlgeschlagen ist. Das tatsächliche Ergebnis steht in einem negativen `responseCode`. Wer nur den HTTP-Status prüft, hält Fehler für Erfolge. Prüfen Sie immer beides.

3. **Die Payload liegt immer unter `data`.** Lesen Sie Ihre Werte aus `data`, nie von der obersten Ebene. Eine Fehlerantwort enthält gar kein `data`-Feld.

4. **Alle Zeitstempel sind ISO 8601 in UTC**, mit einem `Z` am Ende. Das Feld `timezone` eines Meetings steuert nur, wie Einladungen die Zeiten anzeigen. Es verschiebt weder `startTime` noch `endTime`.

## Den richtigen API-Key wählen

Es gibt zwei Arten. Welche Sie haben, entscheidet darüber, was Sie tun können.

| | Kontoebene | Instanzebene |
| --- | --- | --- |
| Erstellt unter | `Kontoeinstellungen` | White-Label-Einstellungen |
| Kann Konten erstellen | nein | ja |
| Kann Meetings verwalten | ja, innerhalb des eigenen Kontos | ja, für jeden User der Instanz |
| Berechtigungen | immer nur Meetings | wählbar: Konten, User, Meetings, Reporting, Branding |
| Wer ihn haben darf | der Kontoinhaber | ausschliesslich der Betreiber der White-Label-Instanz |

> **Hinweis:** Geben Sie Keys auf Instanzebene nie an Kunden weiter. Wer einen solchen Key hat, erstellt Konten und handelt für jeden User der Instanz.

Ein Key auf Kontoebene erreicht immer nur die Meeting-Endpunkte, ganz gleich, welche Berechtigungen Sie ihm sonst zu geben versuchen. Die Plattform erzwingt diese Grenze selbst, sie ist keine blosse Konvention. Einen Key auf Kontoebene können Sie deshalb gefahrlos einem Integrator geben, der nur Meetings planen muss.

Ausserdem müssen Sie auf der White-Label-Instanz die Funktion `accountLevelApiKeys` einschalten. Ist sie aus, weist die Plattform jeden Aufruf mit einem Key auf Kontoebene ab.

### Im Namen eines Users handeln

Standardmässig handelt ein Key als synthetischer API-User, der zu keiner Person gehört. Wollen Sie stattdessen als echter Meeting-Organisator handeln, senden Sie einen dieser Header:

```http
X-USER-ID: <USER-ID>
X-USER-EMAIL: <USER-EMAIL>
```

Senden Sie beide, gewinnt `X-USER-ID` und die Plattform ignoriert `X-USER-EMAIL`. Senden Sie deshalb nur einen davon.

Das funktioniert mit beiden Key-Arten. Ein Key auf Instanzebene handelt als jeder beliebige User der Instanz, ein Key auf Kontoebene nur als Organisator im eigenen Konto. Jedes andere Ziel weist die Plattform ab.

## Die beiden IDs

Ein Meeting hat zwei IDs, und die beiden sind nicht austauschbar. Wer sie verwechselt, macht den häufigsten Fehler im Umgang mit dieser API.

| Name | Sieht aus wie | Wofür sie da ist |
| --- | --- | --- |
| `data.id` | `5e945c36b863b82cefdddf54` | 24 Zeichen hexadezimal. Verwenden Sie sie in jedem API-Aufruf. |
| `data.meetingId` | `9974-7653-8886-0485` | Ziffern mit Bindestrichen. Verwenden Sie sie im Meeting-Link und überall dort, wo Sie das Meeting Personen anzeigen. |

> **Faustregel:** Was Bindestriche hat, ist für Menschen. Was 24 hexadezimale Zeichen hat, ist für die API. `PUT /meeting` akzeptiert zufällig beides, alle übrigen Endpunkte nicht. Nehmen Sie deshalb überall `data.id`, dann liegen Sie immer richtig.

Drei weitere IDs erscheinen in Antworten:

| Name | Quelle |
| --- | --- |
| Konto-ID | `data.id` von `POST /account` |
| User-ID | `data[].id` von `GET /account/admin/{accountId}` |
| Raum-ID | `data.roomId` eines Meetings, wird zusammen mit dem Konto erstellt |

## Konto erstellen

Mit diesem Aufruf erstellen Sie ein Konto und dessen ersten Administrator in einem Schritt. **Nur mit Keys auf Instanzebene.**

| Feld | Typ | Pflicht | Hinweise |
| --- | --- | --- | --- |
| adminEmail | string | ja | Muss auf der ganzen Instanz eindeutig sein. Jede E-Mail-Adresse gibt es nur einmal, auch über verschiedene Konten hinweg. |
| adminFirstname | string | ja | |
| adminLastname | string | ja | |
| adminPreferredLanguage | string | ja | ISO 639-1, zum Beispiel `en` oder `de` |
| accountType | string | ja | `trial`, `standard`, `business`, `professional`, `confidential`, `boardroom`, `classroom`, `boardroomClassroom`, `school`, `payAsYouGo`, `internal` |
| sendPassword | boolean | ja | `true` sendet ein Passwort per E-Mail an `adminEmail`. Beim Testen `false` setzen, damit Sie keine echten Personen anschreiben. |
| paidUntil | ISO 8601 | nein | Nach diesem Zeitpunkt funktioniert das Konto nicht mehr. |

```bash
curl 'https://<DOMAIN-NAME>/api/v6/account' \
  -X POST \
  -H 'X-API-KEY: <API-KEY>' \
  -H 'content-type: application/json' \
  --data-binary '{"sendPassword":true,"accountType":"trial","adminFirstname":"Test","adminLastname":"User","adminEmail":"test-user@example.com","adminPreferredLanguage":"en","paidUntil":"2026-12-31T23:59:59.000Z"}'
```

```json
{
  "responseCode": 0,
  "data": {
    "id": "5e9459c5b863b82cefdddf4f",
    "name": "test-user@example.com",
    "accountType": "trial",
    "numberOfMeetingRooms": 1,
    "paidUntil": "2026-12-31T23:59:59.000Z",
    "accountRooms": []
  }
}
```

`data.id` ist die Konto-ID. Merken Sie sich den Wert, der nächste Aufruf braucht ihn.

Die Antwort beschreibt das Konto, nicht den soeben erstellten Administrator. Dessen User-ID fehlt darin also. Die holen Sie mit dem nächsten Aufruf.

## Kontoadministrator abrufen

Dieser Aufruf liefert die Administratoren eines Kontos. **Nur mit Keys auf Instanzebene.** So kommen Sie an die User-ID des Administrators, den `POST /account` erstellt hat.

```bash
curl 'https://<DOMAIN-NAME>/api/v6/account/admin/<ACCOUNT-ID>' \
  -X GET \
  -H 'X-API-KEY: <API-KEY>'
```

```json
{
  "responseCode": 0,
  "data": [
    {
      "id": "5e9459c5b863b82cefdddf4e",
      "email": "test-user@example.com",
      "firstName": "Test",
      "lastName": "User",
      "preferredLanguage": "en",
      "timezone": "Europe/Zurich"
    }
  ]
}
```

`data` ist ein Array. Bei einem frisch erstellten Konto steht darin ein Eintrag, ein Konto im laufenden Betrieb kann mehrere haben. Suchen Sie deshalb den Eintrag mit der erwarteten E-Mail-Adresse, statt blind `data[0]` zu nehmen.

## Meeting erstellen

Pflicht sind nur zwei Felder, alles Übrige ist optional. Was Sie weglassen, füllt die Plattform mit den Vorgaben des Kontos. Das Beispiel unten sendet trotzdem den vollständigen Satz, und meistens wollen Sie genau das: Ein Meeting ohne `endTime` oder `duration` ist selten so gemeint.

| Feld | Typ | Pflicht | Hinweise |
| --- | --- | --- | --- |
| topic | string | **ja** | |
| startTime | ISO 8601 | **ja** | |
| endTime | ISO 8601 | nein | |
| duration | number | nein | Minuten. Die Plattform leitet den Wert nicht aus den Zeiten ab. Achten Sie also selbst darauf, dass er dazu passt. |
| type | string | nein | `standard`, `offTheRecord`, `boardroom`, `classroom`, `audiobridge` |
| isRecurring | boolean | nein | |
| recurring | object | nein | Senden Sie `{}`, wenn `isRecurring` auf `false` steht. Das Schema steht weiter unten. |
| isRecorded | boolean | nein | Nur bestimmte Meeting-Typen lassen sich aufzeichnen. |
| isDialin | boolean | nein | |
| invitedParticipants | array | nein | `[]` für keine. Den Aufbau eines Eintrags finden Sie weiter unten. |
| meetingPermissionId | string oder null | nein | `null` nimmt die Vorgabe des Kontos. |

Mit einem Key auf Instanzebene ergänzen Sie `X-USER-ID` oder `X-USER-EMAIL`, um im Namen dieses Organisators zu planen.

```bash
curl 'https://<DOMAIN-NAME>/api/v6/meeting' \
  -X POST \
  -H 'X-API-KEY: <API-KEY>' \
  -H 'X-USER-ID: <USER-ID>' \
  -H 'content-type: application/json' \
  --data-binary '{"topic":"My Meeting Topic","startTime":"2026-09-07T09:00:00.000Z","endTime":"2026-09-07T10:00:00.000Z","duration":60,"type":"standard","isRecurring":false,"isRecorded":false,"isDialin":false,"invitedParticipants":[],"recurring":{},"meetingPermissionId":null}'
```

```json
{
  "responseCode": 0,
  "data": {
    "id": "5e945c36b863b82cefdddf54",
    "meetingId": "9974-7653-8886-0485",
    "topic": "My Meeting Topic",
    "startTime": "2026-09-07T09:00:00.000Z",
    "endTime": "2026-09-07T10:00:00.000Z",
    "type": "standard",
    "roomId": "5e9459c5b863b82cefdddf50",
    "isActive": false,
    "isOpen": false,
    "isClosed": true,
    "accountId": "5e9459c5b863b82cefdddf4f",
    "addedByUserId": "5e9459c5b863b82cefdddf4e",
    "timezone": "Europe/Zurich"
  }
}
```

So lesen Sie die Antwort:

- `data.id` brauchen Sie in jedem späteren Aufruf.
- `data.meetingId` zeigen Sie Personen an, und sie gehört in den Meeting-Link.
- **`isClosed` steht bei einem soeben erstellten Meeting auf `true`. Das ist normal.** Es heisst nur, dass noch niemand beitreten kann. Für Moderatoren öffnet ein Meeting rund eine Stunde vor Beginn (`isPreOpen`), für alle anderen rund 15 Minuten vorher (`isOpen`). Werten Sie das nicht als fehlgeschlagenen Aufruf und wiederholen Sie ihn nicht.

### Teilnehmer einladen

Jeder Eintrag in `invitedParticipants` ist ein Objekt:

| Feld | Typ | Pflicht | Hinweise |
| --- | --- | --- | --- |
| email | string | **ja** | Muss eine gültige E-Mail-Adresse sein. |
| name | string | nein | Erscheint in der Einladung. |
| sendInvite | boolean | **ja** | `true` schickt dieser Person eine Einladung mit dem Meeting-Link. `false` fügt sie dem Meeting hinzu, ohne ihr zu schreiben. |

```json
"invitedParticipants": [
  { "email": "anna@example.com", "name": "Anna Meier", "sendInvite": true }
]
```

Setzen Sie `sendInvite` beim Testen auf `false`, aus demselben Grund wie `sendPassword` beim Anlegen eines Kontos: Es ist der Unterschied zwischen einem Testlauf und einer E-Mail an eine echte Person.

### Das recurring-Objekt

Steht `isRecurring` auf `false`, senden Sie `{}`. Steht es auf `true`, gelten diese Felder:

| Feld | Werte |
| --- | --- |
| frequencyType | `never`, `daily`, `weekly`, `monthly`, `yearly` |
| frequency | Zahl. Wie viele Einheiten zwischen zwei Wiederholungen liegen, `2` mit `weekly` also jede zweite Woche. Maximal 52 wöchentlich, 12 monatlich, 10 jährlich. |
| weekDays | An welchen Tagen eine wöchentliche Serie stattfindet, als **zweibuchstabige Codes**: `MO`, `TU`, `WE`, `TH`, `FR`, `SA`, `SU`. |
| monthlyPattern | `day` wiederholt am selben Tag des Monats, `nthWeekDay` am selben Wochentag des Monats, zum Beispiel am zweiten Dienstag. |
| endsType | `never`, `after`, `on` |
| endsAfter | Anzahl Wiederholungen, wenn `endsType` auf `after` steht. Die erste zählt mit, `12` ergibt also 12 Meetings insgesamt. Maximal 365. |
| endsOn | ISO-8601-Datum, wenn `endsType` auf `on` steht |
| exclude | Array von ISO-8601-Daten, die entfallen |

> **`weekDays` erwartet `MO`, nicht `Monday`.** Einen Wert, den wir nicht kennen, verwerfen wir ohne Fehlermeldung. Bleibt einer wöchentlichen Serie danach kein erkannter Tag, wiederholt sie sich schlicht an dem Tag, auf den ihre `startTime` fällt. Nichts schlägt fehl, es lohnt sich also, das gleich richtig zu treffen.

Ein wöchentliches Standup, jeden Montag, 12-mal:

```json
{
  "isRecurring": true,
  "recurring": {
    "frequencyType": "weekly",
    "frequency": 1,
    "weekDays": ["MO"],
    "endsType": "after",
    "endsAfter": 12
  }
}
```

## Der Meeting-Link

Die API liefert keinen Link zurück. Bauen Sie ihn selbst aus der `meetingId` mit den Bindestrichen zusammen:

```text
https://<DOMAIN-NAME>/meeting/<data.meetingId>
```

Für das Beispiel oben ist das `https://<DOMAIN-NAME>/meeting/9974-7653-8886-0485`.

Es ist derselbe Link, den Veeting in seine Einladungs-E-Mails und Kalendereinträge schreibt. Zwei Dinge dazu:

- Er verwendet die `meetingId` mit den Bindestrichen. Die 24-stellige `id` funktioniert hier nicht.
- Der Host ist die Domain, unter der Ihre User den Meetingraum öffnen. Auf den meisten Instanzen ist das dieselbe `<DOMAIN-NAME>`, unter der Sie die API aufrufen. Eine White-Label-Instanz kann aber eine andere Domain hinterlegt haben. Lesen Sie den Wert deshalb aus Ihrer eigenen Konfiguration, statt ihn zu raten.

Ist das Meeting passwortgeschützt, hängt der Einladungslink zusätzlich den Passwort-Hash an. So muss der Empfänger das Passwort nicht eintippen:

```text
https://<DOMAIN-NAME>/meeting/<data.meetingId>?meetingAccessHash=<data.passwordHash>
```

An einen Meeting-Link hängen Sie zusätzlich [Query-Parameter](/de/developer-documentation/query-parameters) an. Damit geben Sie den Teilnehmernamen vor, überspringen den Gerätetest, wählen ein Layout und einiges mehr.

## Ein Meeting zurücklesen

```bash
curl 'https://<DOMAIN-NAME>/api/v6/meeting/5e945c36b863b82cefdddf54' \
  -X GET \
  -H 'X-API-KEY: <API-KEY>' \
  -H 'X-USER-EMAIL: <USER-EMAIL>'
```

Liefert dasselbe Meeting-Objekt zurück wie `POST /meeting`. Erwartet ausschliesslich die 24-stellige `id`.

Sie brauchen das öfter, als es aussieht, denn `PUT` ersetzt und ergänzt nicht: Meeting lesen, die gewünschten Felder ändern, das vollständige Objekt zurücksenden. Ebenso gleichen Sie damit ab, wenn Ihnen ein Webhook entgangen sein könnte, denn [die Zustellung wird genau einmal versucht](/de/developer-documentation/web-hooks), ohne Wiederholung.

Der Aufrufer muss Organisator des Kontos sein, dem das Meeting gehört, oder in dessen `invitedParticipants` stehen.

## Meeting aktualisieren

```text
PUT /api/v6/meeting/<MEETING-ID>/<SEND-UPDATE-TO-PARTICIPANTS>
```

Das zweite Pfadsegment ist ein Boolean und nicht optional:

- `true` schickt allen unter `invitedParticipants` eine aktualisierte Einladung.
- `false` ändert das Meeting stillschweigend.

Dieser Aufruf ersetzt das Meeting, er ist kein Patch. Senden Sie deshalb das vollständige Meeting-Objekt, samt einem `id`-Feld mit der Meeting-ID. Was Sie weglassen, geht verloren.

```bash
curl 'https://<DOMAIN-NAME>/api/v6/meeting/5e945c36b863b82cefdddf54/false' \
  -X PUT \
  -H 'X-API-KEY: <API-KEY>' \
  -H 'X-USER-EMAIL: <USER-EMAIL>' \
  -H 'content-type: application/json' \
  --data-binary '{"id":"5e945c36b863b82cefdddf54","topic":"My Updated Meeting Topic","startTime":"2026-09-07T09:30:00.000Z","endTime":"2026-09-07T10:30:00.000Z","duration":60,"type":"standard","isRecurring":false,"isRecorded":false,"isDialin":false,"invitedParticipants":[],"recurring":{},"meetingPermissionId":null}'
```

## Ein Meeting vorzeitig schliessen

Meetings schliessen sich von selbst, sobald sie zu Ende sind. Wollen Sie eines sofort beenden, schliessen Sie es vorzeitig. Die Plattform entfernt dann alle, die noch im Raum sind.

Schliessen ist nicht Löschen: Der Meeting-Datensatz bleibt bestehen.

```bash
curl 'https://<DOMAIN-NAME>/api/v6/meeting/close' \
  -X POST \
  -H 'X-API-KEY: <API-KEY>' \
  -H 'X-USER-EMAIL: <USER-EMAIL>' \
  -H 'content-type: application/json' \
  --data-binary '{"meetingId":"5e945c36b863b82cefdddf54"}'
```

> **Hinweis:** Trotz seines Namens erwartet das Feld `meetingId` in diesem Body die 24-stellige `data.id`, nicht die `data.meetingId` mit den Bindestrichen.

## Meetings löschen

```bash
curl 'https://<DOMAIN-NAME>/api/v6/meeting/5e945c36b863b82cefdddf54' \
  -X DELETE \
  -H 'X-API-KEY: <API-KEY>' \
  -H 'X-USER-EMAIL: <USER-EMAIL>'
```

Mehrere Meetings löschen Sie in einem Aufruf, indem Sie die IDs mit Kommas trennen:

```text
DELETE /api/v6/meeting/<ID-1>,<ID-2>,<ID-3>
```

Im Body senden Sie optional eine `cancellationMessage` mit. Diesen Text übernimmt die Absage an die eingeladenen Teilnehmer.

## Fehler

Eine Fehlerantwort führt einen negativen `responseCode` und eine `responseMessage` mit, aber kein `data`-Feld. Denken Sie daran: Der HTTP-Status lautet meistens trotzdem 200.

```json
{
  "responseCode": -44,
  "responseMessage": "Input validation failed",
  "errors": []
}
```

| responseCode | Bedeutung | Was zu tun ist |
| --- | --- | --- |
| 0 | Erfolg | |
| -1 | Die Plattform befindet sich in einem Wartungsfenster | Später erneut versuchen |
| -11 | Nicht gefunden | ID prüfen, nicht erneut versuchen |
| -22 | Anwendungsfehler | Nicht blind wiederholen. Der Aufruf hat nicht getan, worum Sie gebeten haben |
| -33 | API-Fehler | Aufbau des Aufrufs prüfen |
| -44 | Eingabevalidierung fehlgeschlagen | Payload korrigieren. `errors` nennt den Grund |
| -55 | Abrechnungsfehler | Das Konto darf diese Aktion nicht ausführen |
| -99 | Authentifizierung fehlgeschlagen | Falscher, inaktiver oder nicht berechtigter API-Key, oder ein User-Header, für den der Key nicht handeln darf. Nicht erneut versuchen |

Pro IP-Adresse dürfen Sie 50 Aufrufe pro Sekunde senden, mit einer kurzen Reserve für Spitzen. Darüber antwortet die Plattform mit **HTTP 429** statt mit einem `responseCode`.

## Häufige Fehler

- HTTP 200 als Erfolg werten, ohne `responseCode` zu prüfen.
- Die `meetingId` mit den Bindestrichen dort übergeben, wo die 24-stellige `id` gefragt ist.
- Den Meeting-Link mit `id` statt mit `meetingId` zusammenbauen.
- `X-USER-ID` zusammen mit `X-USER-EMAIL` senden und erwarten, dass die Plattform die E-Mail-Adresse nimmt.
- `POST /account` mit einem Key auf Kontoebene aufrufen.
- Eine `duration` senden, die nicht zu `startTime` und `endTime` passt.
- Lokale Zeiten ohne das `Z` am Ende senden.
- `isClosed: true` bei einem soeben erstellten Meeting als Fehler deuten.
- An `PUT /meeting` nur die geänderten Felder senden und damit alle übrigen löschen.
- Den API-Key in clientseitigen Code legen.

## Der komplette Ablauf

So richten Sie mit einem Key auf Instanzebene einen Kunden ein und planen dessen erstes Meeting:

```text
POST   /account                       -> data.id           Konto-ID
GET    /account/admin/<ACCOUNT-ID>    -> data[0].id        User-ID
POST   /meeting  + X-USER-ID          -> data.id           für API-Aufrufe
                                         data.meetingId    für den Meeting-Link
PUT    /meeting/<ID>/<true|false>     aktualisieren
POST   /meeting/close                 vorzeitig schliessen
DELETE /meeting/<ID>                  entfernen
```

Mit einem Key auf Kontoebene überspringen Sie die ersten beiden Schritte und senden direkt an `/meeting`.

---

## Die übrige Dokumentation

- [Custom Tools – eigene Widgets im Meetingraum](https://www.veeting.com/de/developer-documentation/custom-tools)
- [Externer Autorisierungsdienst](https://www.veeting.com/de/developer-documentation/external-meeting-authorization-service)
- [iFrame und Web Komponenten](https://www.veeting.com/de/developer-documentation/iframe-and-web-components)
- [JavaScript APIs](https://www.veeting.com/de/developer-documentation/javascript-apis)
- [JavaScript und Typescript APIs](https://www.veeting.com/de/veeting-blocks/apis)
- [Komponenten](https://www.veeting.com/de/veeting-blocks/components)
- [Kontrolle über die Videodarstellung](https://www.veeting.com/de/developer-documentation/video-display-calculator)
- [Parameter in der URL](https://www.veeting.com/de/developer-documentation/query-parameters)
- [Veeting Blocks - Übersicht](https://www.veeting.com/de/veeting-blocks/introduction)
- [Webhooks](https://www.veeting.com/de/developer-documentation/web-hooks)

Alles in einer Datei: https://www.veeting.com/llms-full.txt
