Jitsi Meet
Joining Jitsi Meet rooms — public meet.jit.si and self-hosted instances. Uses lib-jitsi-meet's JS API for clean roster + admit signals.
The jitsi adapter joins Jitsi Meet conferences, both the public
instance at meet.jit.si and any self-hosted Jitsi deployment. Where
possible the adapter uses lib-jitsi-meet's JS API on
window.JitsiMeetJS (and window.APP.conference) instead of DOM
scraping — this is stable across Jitsi versions and locale changes.
Supported URL patterns
| Pattern | Notes |
|---|---|
https://meet.jit.si/<room> | Public meet.jit.si |
https://<your-jitsi>/<room> | Self-hosted (with serverUrl set) |
Public meet.jit.si
curl -X POST https://api.meetbot.dev/api/v1/jobs \
-H "authorization: Bearer $MEETBOT_API_KEY" \
-H "content-type: application/json" \
-d '{
"externalId": "jitsi-demo-2026-05-09",
"meetingUrl": "https://meet.jit.si/myroom-2026",
"platform": "jitsi",
"displayName": "meetbot",
"webhooks": {"onFinalize": "https://yours.example/hook/meetbot"}
}'Self-hosted Jitsi
EU education customers often run their own Jitsi deployment. Pass the
serverUrl in the dispatch metadata, OR set JITSI_SERVER_URL on the
orchestrator to apply the rewrite globally:
# Per-job override:
curl -X POST https://api.meetbot.dev/api/v1/jobs \
-H "authorization: Bearer $MEETBOT_API_KEY" \
-H "content-type: application/json" \
-d '{
"externalId": "uni-lecture-2026-05-09",
"meetingUrl": "https://meet.jit.si/lecture-room-cs101",
"platform": "jitsi",
"metadata": {"jitsi": {"serverUrl": "https://jitsi.eduuni.example"}}
}'
# Global override (orchestrator env):
JITSI_SERVER_URL=https://jitsi.eduuni.exampleWhen serverUrl is set, the bot rewrites the URL's host and protocol
but keeps the room path. So https://meet.jit.si/cs101 →
https://jitsi.eduuni.example/cs101.
Lobby behavior
- Public rooms without the lobby module enabled have no waiting room — the bot joins immediately.
- Lobby-enabled rooms (Jitsi 8.0+ with the moderated-meetings
feature) require moderator approval. The bot polls the
conference.joinedevent from JitsiMeetJS to detect admit. - Password-protected rooms are NOT supported today — the bot has
no password mechanism. Such jobs fail with a
meeting_inaccessibleerror andfailure_code: auth_failure. (M2 ticket to add a per-job password field.)
Captions
Jitsi exposes captions ("Subtitles") via the More menu when the
deployment has the captions service (Jigasi) configured. The adapter
prefers the programmatic toggle (APP.UI.toggleSubtitles()) and
falls back to clicking the menu item. On deployments without Jigasi,
the toggle silently no-ops and the bot's per-speaker audio capture
remains the canonical source for downstream STT.
Roster + competing-bot detection
The adapter prefers the JS API
(APP.conference.listMembers().map(m => m.getDisplayName())) over
DOM scraping for the roster snapshot — cleaner, locale-independent,
no race with tile-mount timing. The same evaluateAutoLeave flow
applies: set autoLeave.onBotDetected: true to have the bot leave on
competing-notetaker detection.
Known quirks
- Some Jitsi builds skip the prejoin pane entirely and drop the bot
straight into the conference. The adapter detects this via
APP.conference.isJoined()and proceeds without filling a name — the display name is set later viaAPP.conference.changeLocalDisplayName(). - Self-hosted Jitsi deployments often have heavily customized
branding, but they keep the lib-jitsi-meet API stable. If you see
jitsi:not admittedon a self-hosted deployment, file an issue with the conference object's shape (runObject.keys(window.APP.conference)in DevTools).
Failure codes
| Jitsi sentinel | failure_code |
|---|---|
| "Password-protected" / requires password | auth_failure |
| "Conference connection failed" (bridge down) | network_loss |
| "Moderator denied your request" | host_denied_admission |
| "You have been kicked" | removed_from_meeting |
Stuck in lobby past afterEntryDelaySeconds | lobby_timeout |