Room configuration
Knock-to-join requires two properties on the room:privacy: 'private'— places tokenless participants in the lobby instead of admitting them directlyenable_knocking: true— allows those lobby participants to ring for admission
Any participant who joins with a meeting token — no matter their permissions — bypasses the lobby and enters the call directly. Only tokenless participants are placed in the lobby.
Using Prebuilt
If you’re using Daily Prebuilt, the lobby UI is built in. Once the room is configured above, also setenable_prejoin_ui on the room, domain, or meeting token and you’re done — Daily handles the waiting room experience for you.
The rest of this guide covers building a custom lobby UI with the call object API.
Waiting participant flow
Join the room
Call
join() without a token. The participant lands in the lobby and accessState() returns { access: { level: 'lobby' } } — they are connected but hidden from other participants.Request access
Call
requestAccess() with a display name. This notifies admins and adds the participant to the waiting list. The returned Promise blocks until the request is decided — you can use the return value directly:Alternatively, use events
If you need to react to access changes in multiple places (e.g. updating different parts of your UI), the event-based approach may be a better fit.
access-state-updated fires when access is granted; a fatal error event with error.type === 'not-allowed' fires when access is denied.Admin flow
Join with admin permissions
Join with a meeting token that grants See meeting token permissions for how to create a token with
canAdmin: ['participants'] (or is_owner: true). Either bypasses the lobby and enters the call directly.canAdmin.Handle participants already waiting
Call Each waiting participant is a
waitingParticipants() immediately after joining to catch anyone who arrived before you.DailyWaitingParticipant:Listen for new arrivals
Subscribe to lobby events to keep your UI in sync:
| Event | Fires when |
|---|---|
waiting-participant-added | A participant calls requestAccess() |
waiting-participant-updated | A waiting participant calls requestAccess() again with a new name |
waiting-participant-removed | A participant is admitted, denied, or leaves on their own |
Admit or deny participants
Use
updateWaitingParticipant() to act on one participant, or updateWaitingParticipants() to act on many at once.Complete example
Openhttps://localhost?t=YOUR_ADMIN_TOKEN for the admin view, or https://localhost (no token) for the waiting participant view.