Mit Webhooks ruft Veeting Ihr System auf, sobald in einem Meeting etwas geschieht. So müssen Sie die API nicht laufend abfragen. Tritt ein Event ein, sendet die Plattform einen HTTP-Aufruf an eine URL, die Sie konfiguriert haben. Im JSON-Body steht das betroffene Objekt.
Sie konfigurieren Webhooks an zwei Stellen. Beide lösen beim selben Event aus:
Konfigurieren Sie beide, ruft die Plattform Ihren Endpunkt beim selben Event zweimal auf, einmal pro Ebene.
Wenn Sie mit einem KI-Coding-Assistenten arbeiten, können Sie den folgenden Text in Ihren Assistenten kopieren und mit einem Satz ergänzen, der beschreibt, was Sie programmieren möchten.
Der Prompt verweist auf unsere Entwicklerdokumentation, die wir für Coding-Assistenten in einer separaten, token-optimierten KI-Version ausliefern.
Lies zuerst diese Seite, bevor Du Code schreibst:
https://www.veeting.com/de/developer-documentation/web-hooks
Sie dokumentiert die Webhooks von Veeting Rooms. Halte Dich an
diese fünf Regeln:
1. Veeting versucht die Zustellung genau einmal. Es gibt keine
Wiederholung. Bestätige schnell, lege die Arbeit in eine Queue
und gleiche bei Bedarf über die REST API ab.
2. Die Payload ist NICHT in responseCode und data verpackt, ausser
bei onMeetingSummaryCreated.
3. Manche Events senden ein Array statt eines Objekts. Alle fünf
Reminder und onMeetingDeleted tun das. Prüfe das, bevor Du
Felder liest.
4. Die Authentifizierung ist ein einziger optionaler
X-API-KEY-Header. Möchte ich den Endpunkt geschützt haben, dann
prüfe diesen Header und weise alles andere ab.
5. Frage mich, ob der Webhook auf Instanzebene oder auf Kontoebene
konfiguriert ist. Beide können aktiv sein, was zwei Aufrufe pro
Event bedeutet.
Was ich bauen möchte:Wir versuchen die Zustellung genau einmal. Es gibt keine Wiederholung, kein Backoff und keine Dead-Letter-Queue. Ist Ihr Endpunkt nicht erreichbar oder antwortet er zu spät oder mit einem Fehlerstatus, loggen wir das Event auf unserer Seite. Auf Ihrer Seite ist es verloren. Richten Sie sich darauf ein: rasch bestätigen, die Arbeit intern in eine Queue legen und bei Bedarf das Meeting mit GET /meeting/{id} zurücklesen, statt darauf zu vertrauen, dass jedes Event angekommen ist.
Antworten Sie schnell. Für die Zustellung ist kein Timeout konfiguriert. Ein langsamer Endpunkt hält deshalb eine Verbindung offen, statt zügig zu scheitern. Geben Sie ein 2xx zurück, sobald Sie die Payload angenommen haben, und erledigen Sie die Arbeit danach.
Der Body ist das Objekt selbst, kein Wrapper. Anders als bei der REST API steckt eine Webhook-Payload nicht in responseCode und data. Zwei Events weichen ab: onMeetingSummaryCreated kommt in responseCode und data verpackt an, und onMeetingRecordingCreated kommt als Objekt an, in dem das Meeting steckt, statt als Meeting selbst. Beide sind unten beschrieben.
Prüfen Sie die Form der Payload, bevor Sie sie lesen. Manche Events senden ein einzelnes Objekt, andere ein Array. Welche das sind, steht unten.
Sie konfigurieren jeden Webhook einzeln, mit vier Einstellungen:
| Einstellung | Bedeutung |
|---|---|
| enabled | Ob dieser Webhook überhaupt auslöst |
| url | Der Endpunkt, den wir aufrufen |
| method | POST, PUT oder DELETE. Leere oder unbekannte Werte fallen auf POST zurück. |
| apiKey | Optional. Siehe unten. |
Setzen Sie apiKey, sendet die Plattform ihn bei jedem Aufruf als X-API-KEY-Header. Ihr Endpunkt weist damit alle Aufrufe ohne diesen Header ab. Lassen Sie das Feld leer, sendet die Plattform gar keinen solchen Header.
Mehr Authentifizierung hat ein Webhook-Aufruf nicht. Einen Endpunkt ohne konfigurierten API-Key ruft jeder auf, der seine URL kennt.
content-type: application/json sendet die Plattform immer mit.
Es gibt 14 Events.
| Event | Löst aus, wenn | Payload |
|---|---|---|
onMeetingScheduled | Ein Meeting erstellt wird | Meeting |
onMeetingUpdated | Ein Meeting geändert wird | Meeting |
onMeetingClosed | Ein Meeting geschlossen wird, automatisch oder manuell | Meeting |
onMeetingDeleted | Meetings gelöscht werden | Array von Meeting |
onMeetingCancelled | Ein einzelner Termin einer Serie abgesagt wird | { meeting, day } |
onMeetingJoined | Jemand einem Meeting beitritt | MeetingParticipantsStatus |
onMeetingLeft | Jemand ein Meeting verlässt | MeetingParticipantsStatus |
onMeetingSummaryCreated | Eine Summary erstellt wird, üblicherweise rund fünf Minuten nach dem Schliessen | MeetingSummary, verpackt |
onMeetingRecordingCreated | Ein aufgezeichnetes Meeting zusammengefügt wurde | Aufzeichnung |
onMeetingsReminder15MinutesBefore | 15 Minuten vor Meeting-Beginn | Array von Meeting |
onMeetingsReminder30MinutesBefore | 30 Minuten vor Meeting-Beginn | Array von Meeting |
onMeetingsReminder60MinutesBefore | 60 Minuten vor Meeting-Beginn | Array von Meeting |
onMeetingsReminder24HoursBefore | 24 Stunden vor Meeting-Beginn | Array von Meeting |
onMeetingsReminder48HoursBefore | 48 Stunden vor Meeting-Beginn | Array von Meeting |
Zwei Dinge zu den Remindern übersieht man leicht:
Diese Payload senden onMeetingScheduled, onMeetingUpdated und onMeetingClosed. Es ist dasselbe Objekt, das die REST API bei POST /meeting zurückgibt, hier gekürzt:
{
"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",
"duration": 60,
"type": "standard",
"roomId": "5e9459c5b863b82cefdddf50",
"isRecurring": false,
"isRecorded": false,
"isDialin": false,
"invitedParticipants": [],
"agenda": "",
"whitelabelId": "5c737902b377b0f7fbf81fce",
"accountId": "5e9459c5b863b82cefdddf4f",
"addedByUserId": "5e9459c5b863b82cefdddf4e",
"addedByUserEmail": "test-user@example.com",
"addedByUserName": "Test User",
"timezone": "Europe/Zurich",
"isActive": false,
"isOpen": false,
"isClosed": true
}Die beiden IDs verhalten sich genau wie in der REST API: Verwenden Sie id, wenn Sie zurück in die API rufen, und meetingId, wenn Sie einen Link bauen oder das Meeting jemandem anzeigen.
Diese Payload senden onMeetingDeleted und alle fünf Reminder. Es ist dasselbe Objekt wie oben, in einem Array:
[
{ "id": "5e945c36b863b82cefdddf54", "meetingId": "9974-7653-8886-0485", "topic": "My Meeting Topic" }
]Bei onMeetingDeleted kann jedes Meeting zusätzlich ein Feld cancellationMessage mitführen. Darin steht der Text, den der Organisator beim Löschen angegeben hat.
Diese Payload sendet onMeetingCancelled, wenn jemand einen einzelnen Termin einer Serie absagt und nicht die ganze Serie. Das Meeting steckt verschachtelt im Body, und day bezeichnet den Termin:
{
"meeting": { "id": "5e945c36b863b82cefdddf54", "meetingId": "9974-7653-8886-0485", "isRecurring": true },
"day": "2026-09-14"
}Diese Payload senden onMeetingJoined und onMeetingLeft:
{
"meetingId": "5df78199c015b37195230596",
"meetingToken": "0000-0000-0000-0000",
"isNamedRoom": false,
"participant": {
"name": "Joe Doe",
"email": "joe@example.com",
"meetingParticipantId": "4edaf0d2-cb6c-42f1-a266-4ae7d971f2e6",
"isModerator": false
},
"totalNumberOfGuests": 3,
"totalNumberOfModerators": 1,
"whitelabelId": "5c737902b377b0f7fbf81fce",
"accountId": "5e9459c5b863b82cefdddf4f"
}Hinweis: Hier enthält
meetingIddie 24-stelligeiddes Meetings, undmeetingTokendie Nummer mit den Bindestrichen. Das ist genau umgekehrt zur Benennung überall sonst. Lesen Sie hier also besonders genau.
Diese Payload sendet onMeetingSummaryCreated. Es ist die einzige, die in responseCode und data verpackt ankommt:
{
"responseCode": 0,
"data": {
"id": "5f7d49eb62e8f9a43b23f986",
"meetingId": "5f7d49e662e8f9a43b23f983",
"meetingType": "boardroom",
"agenda": "",
"minutes": "",
"participants": [
{
"name": "Participant 1",
"durations": [
{ "action": "joined", "timestamp": 1602046445811 },
{ "action": "left", "timestamp": 1602046670808 }
],
"info": {
"browserName": "Chrome",
"browserVersion": "82.0.4062.0",
"osName": "macOS",
"osVersion": "10.15.6",
"platformType": "desktop",
"platformVendor": "Apple"
}
}
],
"documents": [],
"pdf": null,
"accountId": "5c73790ab377b0f7fbf81fde",
"isNamedRoom": false,
"isRecordingPrepared": false,
"sfuHostname": "ch-01-sfu-02.wlvmr.net",
"meetingQuestions": [],
"meetingConversationDuration": 25,
"meetingConversationStartToEndDuration": 25,
"meetingParticipantsStartToEndDuration": 35,
"meetingStartToEndDuration": 60
}
}Die vier Dauer-Felder messen Unterschiedliches. Alle Werte sind Sekunden:
| Feld | Was es misst |
|---|---|
| meetingConversationDuration | Wie lange mindestens zwei Personen gleichzeitig im Raum waren |
| meetingConversationStartToEndDuration | Vom ersten Moment, in dem zwei Personen zusammen im Raum waren, bis zum letzten |
| meetingParticipantsStartToEndDuration | Vom Beitritt der ersten Person bis zum Verlassen der letzten |
| meetingStartToEndDuration | Die geplante Dauer, einschliesslich Verlängerung |
Diese Payload sendet onMeetingRecordingCreated. Anders als die übrigen ist sie ein Wrapper: Meeting und Summary stecken darin, statt selbst der Body zu sein.
{
"meeting": { "id": "5e945c36b863b82cefdddf54", "meetingId": "9974-7653-8886-0485", "topic": "My Meeting Topic" },
"summary": { "id": "5f48a701ee0c388a879bffa7" },
"mergedRecordingUrl": "https://<recording-host>/prepared/<meeting>/<token>.webm",
"recordingUrls": [
"video-file-1.webm",
"video-file-2.webm",
"video-file-3.webm"
],
"emailNotificationRecipients": ["organizer@example.com"]
}| Eigenschaft | Bedeutung |
|---|---|
| meeting | Das vollständige Meeting-Objekt, wie oben beschrieben |
| summary | Die Summary, zu der diese Aufzeichnung gehört |
| mergedRecordingUrl | Die einzelne, zusammengefügte Aufzeichnung |
| recordingUrls | Die einzelnen Teile, aus denen sie entstand, so wie der Aufzeichnungs-Host sie meldet |
| emailNotificationRecipients | Wen die Plattform gleich über diese Aufzeichnung informiert |
Hinweis: Lesen Sie die IDs des Meetings aus
meeting.idundmeeting.meetingId. Auf oberster Ebene dieser Payload gibt es keinmeetingId.
onMeetingSummaryCreated als unverpacktes Objekt lesen. Es ist die einzige verpackte Payload.meetingId in der Join- und Leave-Payload als Nummer mit Bindestrichen lesen. Dort ist es die 24-stellige id, und meetingToken ist die mit den Bindestrichen.apiKey bei einem Endpunkt leer lassen, der Daten verändert.Sprechen Sie mit unserem Team über Ihre Pläne.