# Custom Tools – eigene Widgets im Meetingraum

Source: https://www.veeting.com/de/developer-documentation/custom-tools

## Übersicht

Mit Custom Tools bringen Sie Ihre eigene Oberfläche in den Meetingraum, gleichberechtigt neben Video, Dokumente und Whiteboard. Ein Tool besteht aus einem Icon, einem Label und einer Ihrer Seiten, die der Raum in einem iFrame darstellt.

Sie konfigurieren die Tools in den Systemeinstellungen einer White-Label-Instanz. **Pro Instanz gibt es genau eine Konfiguration**, und standardmässig keine.

## 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/custom-tools

Sie dokumentiert Custom Tools im Veeting Rooms Meetingraum.
Halte Dich an diese fünf Regeln:

1. Ein API-Endpunkt muss ein REINES JSON-Array von Tools
   zurückgeben, kein Objekt mit einer data-Eigenschaft.
2. meetingId ist die 24-stellige ID, meetingToken die Nummer mit
   den Bindestrichen. Vertausche die beiden nicht.
3. Eine feste iFrame-URL erhält culture, aber nie moderatorToken.
   Ein API-Endpunkt erhält moderatorToken, aber nie culture.
4. moderatorToken hängen wir immer an den API-Aufruf an, sein
   Vorhandensein beweist also nichts. Prüfe den Wert selbst.
5. Der Raum zeigt höchstens fünf Tools an, und ein Tool ohne
   iFrameUrl überspringt er.

Was ich bauen möchte:
```

## Die Quelle wählen

Sie stellen ein Tool auf zwei Wegen bereit. Eine Instanz nutzt jeweils einen davon.

| Quelle | Was sie tut | Verwenden Sie sie, wenn |
| --- | --- | --- |
| iFrame-URL | Eine feste URL, für alle sichtbar | Alle Teilnehmer dasselbe Tool sehen |
| API-Endpunkt | Wir rufen für jeden Teilnehmer Ihren Endpunkt auf, und Sie geben die passenden Tools zurück | Die Tools sich pro Teilnehmer unterscheiden oder Sie mehrere brauchen |

Wie Sie sich auch entscheiden: Die Funktion muss für die Instanz aktiviert sein, sonst erscheint nichts.

## Eine feste iFrame-URL

![Custom tools iFrame configuration](/assets/img/documentation/custom-tools-iframe-configuration.png)

Liefern Sie die URL über HTTPS aus. Ihr Webserver muss zudem Header senden, die dem Browser erlauben, Ihre Seite innerhalb unserer Seite darzustellen.

### Das Label

Sie geben entweder einen festen String an oder eine Liste von Übersetzungen, getrennt durch Senkrechtstriche.

| Label | Ergebnis |
| --- | --- |
| My Custom Tool | Zeigt immer «My Custom Tool», in welcher Sprache der Meetingraum auch dargestellt wird. |
| en:My Custom Tool\|de-CH:Mein eigenes Tool\|fr:Mon outil personnalise | Auf Englisch erscheint «My Custom Tool», auf Deutsch «Mein eigenes Tool» und so weiter. Fehlt eine Sprache in der Liste, greift der englische Eintrag. Fehlt auch dieser, greift der erste Eintrag. |

### Was wir an Ihre URL anhängen

Wir ergänzen Query-Parameter, damit Ihre Seite weiss, wer sie betrachtet:

| Parameter | Wert |
| --- | --- |
| participantName | Der Name des Teilnehmers |
| participantId | Die eindeutige ID des Teilnehmers |
| meetingId | Die 24-stellige Meeting-ID, zum Beispiel `5349b4ddd2781d08c09890f3` |
| meetingToken | Die Meetingnummer mit Bindestrichen, zum Beispiel `0000-0000-0000-0000` |
| culture | Das Locale des Teilnehmers beim Betreten des Raums, zum Beispiel `en`, `en-US` oder `de-DE` |

Zwei Dinge sollten Sie wissen:

- **`moderatorToken` senden wir hier nicht.** Den erhält nur ein API-Endpunkt, siehe unten. Mit einer festen iFrame-URL erkennen Sie deshalb nicht, ob der Betrachter Moderator ist.
- Enthält Ihre URL bereits ein `?`, hängen wir die Parameter mit `&` an. Eine URL mit eigenem Query-String funktioniert also weiterhin.

Wir URL-codieren die Werte. Decodieren Sie sie also, bevor Sie sie verwenden. Ein Name mit einem Leerzeichen oder einem `&` kommt so unversehrt bei Ihnen an.

## Ein API-Endpunkt

Mit einem API-Endpunkt entscheiden Sie pro Teilnehmer, welche Tools erscheinen. Bis zu fünf dürfen es sein.

![Custom tools API configuration](/assets/img/documentation/custom-tools-api-configuration.png)

Tritt jemand bei, rufen wir Ihren Endpunkt auf und zeigen, was er zurückgibt.

![Ein Browser betritt das Meeting, der Meeting-Server ruft Ihren API-Endpunkt mit Angaben zu Teilnehmenden und Meeting auf, Ihr Endpunkt entscheidet über die Werkzeuge und liefert bis zu fünf zurück, und der Meetingraum zeigt sie an](/assets/img/documentation/custom-tools-api-workflow.de.svg)

```mermaid
sequenceDiagram
    autonumber
    participant B as Webbrowser
    participant V as Web-Meeting-Server
    participant I as Ihr API-Endpunkt
    B->>V: Betritt das Meeting
    V->>I: GET, mit Angaben zu Teilnehmenden und Meeting
    Note over I: Entscheidet, welche Werkzeuge<br/>diese Person sieht
    I-->>V: Liefert bis zu fünf Werkzeuge
    V-->>B: Liefert die Liste der Werkzeuge
    Note over B: Zeigt die Werkzeuge<br/>im Meetingraum
```

### Der Aufruf

Wir schicken ein HTTP `GET` und legen Ihr konfiguriertes Geheimnis in den Header `X-API-KEY`:

| Parameter | Wert |
| --- | --- |
| participantName | Der Name des Teilnehmers |
| participantId | Die eindeutige ID des Teilnehmers |
| meetingId | Die 24-stellige Meeting-ID |
| meetingToken | Die Meetingnummer mit Bindestrichen |
| moderatorToken | Der Moderatoren-Token des Teilnehmers |

> **Hinweis:** An einen API-Endpunkt senden wir `culture` **nicht**, `moderatorToken` hängen wir dagegen **immer** an. Bei einem Teilnehmer ohne Moderationsrechte enthält er keinen gültigen Token. Prüfen Sie deshalb den Wert selbst und nicht, ob der Parameter vorhanden ist. Alle Werte sind URL-codiert.

```bash
curl 'https://<CUSTOM-TOOL-API-URL>?participantName=Joe%20Doe\
&participantId=XXXXX\
&meetingId=5349b4ddd2781d08c09890f3\
&meetingToken=0000-0000-0000-0000\
&moderatorToken=YYYYY' \
  -H 'X-API-KEY: <CUSTOM-TOOL-API-KEY>' \
  -H 'accept: application/json, text/plain, */*'
```

### Die Antwort

Antworten Sie mit HTTP 200 und einem **reinen JSON-Array** von Tool-Objekten. Verpacken Sie es nicht. Anders als bei der REST API entpackt hier niemand eine `data`-Eigenschaft für Sie.

| Eigenschaft | Bedeutung |
| --- | --- |
| iFrameUrl | Die URL, die wir darstellen. **Fehlt sie, überspringen wir das Tool.** |
| toolIcon | Ein SVG-String für das Icon. Alles über 50'000 Zeichen verwerfen wir, und das Tool erhält das Standard-Icon. |
| labels | Ein Array von Label-Objekten |

Ein Label-Objekt:

| Eigenschaft | Bedeutung |
| --- | --- |
| culture | Das Locale dieses Labels, zum Beispiel `en`, `en-US` oder `de-DE` |
| label | Der anzuzeigende Text, zum Beispiel «My Custom Tool» |

```json
[
  {
    "iFrameUrl": "https://www.example.com/custom-tool-1",
    "toolIcon": "<svg>...</svg>",
    "labels": [
      {
        "culture": "en-US",
        "label": "Custom tool 1"
      },
      {
        "culture": "de",
        "label": "Spezialtool 1"
      }
    ]
  }
]
```

### Grenzen und Fallbacks

- **Höchstens fünf Tools.** Alles nach dem fünften Eintrag Ihres Arrays ignorieren wir.
- Ein Tool ohne `iFrameUrl` überspringen wir vollständig.
- Fehlt `labels` oder ist das Array leer, erhält das Tool das Label «Custom tool».
- Kann der Meetingraum das Locale des Teilnehmers nicht zuordnen, nimmt er das erste Label Ihres Arrays. Setzen Sie Ihren bevorzugten Standard deshalb an den Anfang.
- Antwortet Ihr Endpunkt mit einem Fehler, läuft er in einen Timeout oder gibt er kein Array zurück, zeigen wir keine Custom Tools an. Das Meeting läuft normal weiter.

## Häufige Fehler

- Sie vertauschen `meetingId` und `meetingToken`. `meetingId` ist die 24-stellige, `meetingToken` die mit den Bindestrichen.
- Sie erwarten `moderatorToken` bei einer festen iFrame-URL, wo wir ihn nie senden.
- Sie erwarten `culture` bei einem API-Endpunkt, wo wir es nie senden.
- Sie werten das Vorhandensein von `moderatorToken` als Nachweis für Moderationsrechte.
- Sie verpacken die API-Antwort, statt ein reines Array zurückzugeben.
- Sie geben mehr als fünf Tools zurück und wundern sich, wo die übrigen geblieben sind.
- Sie liefern das Tool über HTTP aus oder mit Headern, die das Einbetten verbieten.
- Sie lesen einen Teilnehmernamen direkt aus dem Query-String, ohne ihn zu decodieren.

---

## Die übrige Dokumentation

- [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)
- [Veeting Rooms REST APIs](https://www.veeting.com/de/developer-documentation/api-usage)
- [Webhooks](https://www.veeting.com/de/developer-documentation/web-hooks)

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