A meeting in TeleQuick is not a stored object. It is a room name plus a token. The conferencing engine (mod_meet) has no create API: it materialises a room the first time a participant joins with a token that carries that name, and it reaps the room when the last participant leaves. Everything the console shows under Rooms is therefore live engine state, read back from the engine on each poll — not a database table you can pre-seed, rename, or archive.

When a room is created and when it is reaped

  1. You pick a name and mint a token for it.
  2. A client joins with that token. The engine creates the room at that moment. This is the only way a room comes into existence — there is no rooms.create procedure and no “create room” action in the console.
  3. The room is listed by meet.rooms.list with a participant count and a createdAt timestamp (the console renders createdAt as the room’s “up” time).
  4. When the last participant leaves, the engine reaps the room. Its name disappears from the listing, along with its participant and track state.
Because creation is join-driven, a name you have only minted a token for does not appear anywhere until media actually starts flowing. If you just clicked New meeting and the room is not in the list yet, nobody has joined it yet. Reaping is the engine’s decision, not the console’s. The console does not display, and this page does not define, a fixed delay between the last leave and the reap — treat an empty-but-listed room as a normal transient state rather than an error. See Empty rooms: why one can still be listed.

Room name grammar

A room name is carried in a token claim, validated by the control plane’s roomName schema, and then used as an element of the MoQT namespace for the room’s tracks. That last point is the constraint that matters: the name has to survive being placed in a namespace path, so it is restricted to unreserved characters only — no percent-encoding, no slashes, no spaces, nothing that would need escaping to sit in a namespace element. Practical consequences:
  • A name is an opaque identifier, not a title. Put the human-readable subject of the meeting in your own application data, not in the room name.
  • Two different names are two different rooms, even if they differ only in case or punctuation. Nothing normalises them for you.
  • A name that the schema rejects fails at the control plane before the engine is ever contacted, so the failure surfaces as a rejected mutation rather than as a transport-level join error.

Names the console mints

New meeting does not ask you for a name; it generates one and navigates straight into the join flow. The generated shape is:
The x positions are drawn with crypto.getRandomValues from a 32-character alphabet — abcdefghijkmnpqrstuvwxyz23456789 — which is the lowercase alphanumerics with the visually ambiguous characters (l, o, 0, 1) removed. The names are random rather than sequential, so holding one room’s name tells you nothing about any other room’s name. You are not required to use this shape. It is simply a name that is guaranteed to satisfy the schema, safe to read aloud, and not guessable from a sibling.

How the name becomes a namespace element

The room name is the element that separates one room’s media from another’s in the MoQT namespace. Tokens are scoped to namespaces, so the room name in the token is what gates publish and subscribe for that room: a token minted for one room name cannot carry media for a different one. Two things follow from this:
  • Treat the name as a capability-adjacent value. Anyone who holds a valid token for a name can join that room. Do not derive names from sequential identifiers, and do not reuse a name across unrelated meetings if the tokens for the earlier meeting have not expired.
  • A name change is a new room. There is no rename. Moving a meeting to a different name means minting new tokens and having clients join the new name; the old room reaps itself once its last participant leaves.

Empty rooms: why one can still be listed

Opening Participants on a room can show “Nobody is in this room”. That is not a bug and not an inconsistent read. It means the engine still holds the room, but no participant is currently in it — the room has not been reaped yet. You can also see a room that looks emptier than its own header suggests:
  • The room header reports numParticipants and, when it differs, the number of participants that are hidden (participants whose hidden permission is set). Hidden participants are counted in the room, and the difference between the total and the visible count is shown explicitly in the room subtitle.
  • A participant that has just joined can appear with no tracks at all. The engine registers a track when it first carries media, so an empty track list means nothing has arrived from that participant yet — it is not a statement that they are refusing to publish.
The listing is polled, not pushed: the room list refetches every 15 s and an open participant table refetches every 10 s. A room that was reaped a moment ago can therefore still be on screen until the next poll. Refresh forces a re-read.

Closing a room versus waiting for it to reap

The Close action on a room card calls meet.rooms.remove. It does not delete a stored record, because there is no stored record. It ejects every participant currently in the room, which is what causes the engine to drop the room. Removing a single participant (meet.participants.remove) is the narrower version of the same idea: that person is disconnected immediately, and they can rejoin with a valid token. Neither action revokes anything. If a close is rejected, the console surfaces the error on the room card rather than optimistically dropping the row — a room that is still listed after a failed close is still open.

Rejoining a name after a close

Because a close only ejects participants, and because tokens are unaffected by it, a join that arrives after the close re-creates the room under the same name. This includes joins that were already in flight when you clicked Close: they are racing the eject, and whichever lands last wins. A client that reconnects automatically will therefore reappear in a room you just closed. Closing a room is consequently a way to clear a room, not a way to end a meeting permanently. To make a name unjoinable you have to stop honouring it at token-mint time — stop minting tokens for that name, and let the tokens already out there expire. See Authentication for how token expiry and signing-key rotation interact. The reverse case is the ordinary one: a room that reaped itself is recreated by the next join with a valid token for that name, with fresh participant, track, and permission state. Nothing carries over from the previous occupancy.

Joining requires a reachable engine

Rooms are read from the engine, so the console checks meet.status before it lets you into a room. The check distinguishes three states, and they mean different things for room lifecycle: New meeting is disabled unless the engine is reachable. This is deliberate: joining a room on an unreachable engine fails at the transport with a much less legible error than a disabled button. Configuration is per organization — each org has its own engine address and its own rotatable signing key — so a room name is only ever meaningful within the org whose engine holds it.
  • Authentication — minting the token that carries the room name, and namespace scoping
  • Telemetry — the operational streams the gateway emits