meetbot / docs
Per-platform

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

PatternNotes
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.example

When serverUrl is set, the bot rewrites the URL's host and protocol but keeps the room path. So https://meet.jit.si/cs101https://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.joined event from JitsiMeetJS to detect admit.
  • Password-protected rooms are NOT supported today — the bot has no password mechanism. Such jobs fail with a meeting_inaccessible error and failure_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 via APP.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 admitted on a self-hosted deployment, file an issue with the conference object's shape (run Object.keys(window.APP.conference) in DevTools).

Failure codes

Jitsi sentinelfailure_code
"Password-protected" / requires passwordauth_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 afterEntryDelaySecondslobby_timeout

On this page