Zoom Skip Waiting Room

Skip the Zoom waiting room by providing the meeting host's ZAK token

Zoom bots join the waiting room by default when a waiting room is enabled. To let the bot skip the waiting room without a host manually admitting it, provide a ZAK token minted for the meeting host via zoom.zak_url.

Prerequisite: Signed-in Zoom bots

Skipping the waiting room builds on signed-in Zoom bots. Implement that flow first: a Zoom OAuth app, a zoom.zak_url callback that returns a plaintext ZAK, and just-in-time token minting.

This guide only changes whose ZAK you mint — it must belong to the meeting host, not a shared service account.

❗️

Common mistake

Following the Signed-in Bots: Zoom guidance and minting ZAKs from one dedicated service account will not skip the waiting room. That pattern is correct for authenticated-join meetings, but Zoom will still place the bot in the waiting room unless the ZAK belongs to the meeting host.

⚠️

ZAK tokens are short-lived. Mint them just-in-time when Recall requests your callback — do not pre-generate and cache them for later joins.

Implementation

Step 1: Resolve the host in your zoom.zak_url callback

Recall will GET your callback and expects a plaintext ZAK in the response body (not JSON).

The minting mechanics are the same as signed-in Zoom bots. The difference is your callback must resolve the correct host credentials for that bot/meeting (for example via a query parameter you set when creating the bot):

def validate_request(request) -> bool:
  """Validate the authenticity of the request.
  https://docs.recall.ai/docs/authenticating-requests-from-recallai
  """
  pass

def retrieve_host_zak_token(host_id: str) -> str:
  """Load the host's Zoom OAuth credentials, refresh if needed,
  then call Zoom's userZak endpoint and return the token string.
  """
  pass

# HTTP handler for https://example.com/recall/callbacks/zak
def http_handler(request):
  if not validate_request(request):
    return HttpResponse(code=401)

  host_id = request.query_parameters["host_id"]
  zak_token = retrieve_host_zak_token(host_id)
  return HttpResponse(body=zak_token)

Step 2: Create the bot with zoom.zak_url

curl -X POST "https://RECALL_REGION.recall.ai/api/v1/bot/" \
  -H "Authorization: Token YOUR_RECALL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "meeting_url": "YOUR_ZOOM_MEETING_URL",
    "zoom": {
      "zak_url": "https://YOUR_SERVER/recall/callbacks/zak?host_id=HOST_ID"
    }
  }'

When the bot joins, Recall calls your zak_url, receives the host ZAK, and uses it to authenticate the bot so it can skip the waiting room.


FAQ

Can I use a service-account (or any non-host) ZAK to skip the waiting room?

No. For skipping the waiting room, the ZAK must be minted for the meeting host. A foreign-account / shared service-account ZAK will leave the bot in the waiting room.

Does each meeting host need to connect Zoom?

Yes for this guide's host-ZAK flow. Store per-host OAuth credentials and resolve the correct host when your zak_url is called.

At scale (many hosts / white-label tenants), plan for a connect-Zoom step per host (or an account-level Zoom authorization model that can mint that host's ZAK). A single shared Zoom user cannot cover skip-waiting-room for arbitrary external hosts.

Does the host need to already be in the meeting?

No for host ZAK. You can mint and provide the host's ZAK before the host joins.

That differs from OBF tokens, which require the associated user to already be in the meeting and remove the bot if that user leaves.

Why is my bot still in the waiting room?

Check these first:

  1. Wrong ZAK identity — token was minted for a service account / non-host user
  2. Host never connected Zoom — no OAuth credentials to mint a host ZAK from
  3. Stale tokens — expired ZAK or expired underlying OAuth access token
  4. Bad callback responsezak_url returned JSON, quotes, or an empty body instead of plaintext
  5. Join-token-only configjoin_token_url without a accompanying ZAK/OBF on the Meeting SDK path
  6. Waiting room is expected — if no host ZAK (and no successful join-token+ZAK/OBF path) is configured, the bot behaves like a normal guest

How can I tell that skip-waiting-room worked?

On a successful host-ZAK join, the bot should move from joining into the call without sitting in in_waiting_room waiting for manual admit.

If you see joining_callin_waiting_room (and especially if you later see recording_permission_allowed only after someone admits the bot), the host ZAK was not applied successfully for that meeting.


Did this page help you?