Skip to main content

Zoom OAuth app setup for WordPress

Connecting Zoom to a WordPress LMS means building an app in the Zoom Marketplace. Most setups fail for one of three reasons: the wrong app type, a missing scope, or a token that quietly kept its old permissions.

This guide covers all three.


Which app type do you need?

Zoom offers several app types and the names do not make the choice obvious. For a WordPress integration that creates meetings and reads attendance, here is how they differ.

App type Use it when
OAuth (account-level) Your site acts on behalf of one Zoom account — creating meetings, reading participant reports. This is the one most LMS integrations need.
Server-to-Server OAuth Machine-to-machine access with no user authorisation step. Useful for background jobs, but it cannot be distributed.
Meeting SDK Embedding the meeting inside your own page so students join in the browser. It does not create meetings or read attendance — it is display only, and it is a separate app alongside your OAuth app.

A common misconception: you do not need a Meeting SDK app to track attendance. Meeting creation and attendance both run through the OAuth app. The SDK is only for in-page joining.

Who can create the app

The Zoom user authorising the app must have admin-level privileges, or be the account owner. Account-level OAuth apps with broad scopes can only be authorised by account admins, or by users granted marketplace and developer permissions.

You also need a paid Zoom plan. Participant reports, which attendance depends on, are not available on Basic accounts.

If you are setting this up for a client, this is the step to resolve first. It routinely blocks everything else.

Creating the app

  1. Log in to the Zoom Marketplace as the account owner or an admin
  2. Go to Develop → Build App
  3. Choose OAuth
  4. Name the app and click Create

Keep the app private unless you intend to publish it. A private app works across your own account without going through Zoom’s review process.

Redirect URL and webhook URL

Two different URLs, easy to mix up:

  • Redirect URL — where Zoom sends the user back after they approve the connection. This comes from your plugin’s settings screen.
  • Webhook endpoint URL — where Zoom sends event notifications, such as a meeting ending. Also from your plugin’s settings.

Both must match exactly, including https:// and any trailing slash. A redirect URL that differs by one character produces a mismatch error at the moment of connecting, with no other explanation.

While you are on this screen, copy the Secret Token. It is used to verify that incoming webhooks genuinely came from Zoom.

The scopes you need

Scopes are the permissions the app requests. Missing one does not fail at setup — it fails later, with an error that does not obviously point back here.

Scope What breaks without it
meeting:write:meeting:admin Meetings cannot be created from WordPress at all
meeting:read:meeting:admin Meeting details never sync back, so the join link and times may be wrong
meeting:update:meeting:admin Rescheduling in WordPress silently fails to reach Zoom
meeting:delete:meeting:admin Deleted lessons leave orphaned meetings on the Zoom account
user:read:user:admin The connection cannot identify which Zoom account it is attached to
report:read:list_meeting_participants:admin Attendance is never retrieved. Meetings work, nobody is marked complete

That last one is the scope people forget. Everything appears to work — meetings get created, students join — and then no course progress is recorded, because the integration was never allowed to read the participant report.

Event subscriptions

Attendance arrives through webhooks, not polling. Without event subscriptions the integration has no idea a session ended.

  1. Turn on Event Subscriptions in the app
  2. Add your webhook endpoint URL
  3. Subscribe to at least meeting.started and meeting.ended

Zoom validates the endpoint when you save, so the plugin must be installed and the Secret Token in place before this step will succeed.

The token behaviour that breaks most setups

Adding scopes to the app does not change an existing connection. An access token carries whatever permissions were granted at the moment it was authorised, and refreshing the token preserves that original set. It does not pick up scopes added afterwards.

This is why the usual troubleshooting loop fails. You hit a permission error, add the missing scope, refresh the page, and get the same error — because the token in use still holds the old permissions.

The fix: after changing scopes, disconnect the Zoom account in your plugin settings and connect again. That forces a fresh authorisation and issues a token with the full set.

In LiveClass Sync that is LiveClass Sync → Settings → Disconnect Zoom Account, then Connect Zoom.

Verifying it works

Four checks, in order. Each isolates a different part of the chain:

  1. Connection. The plugin settings show the connected Zoom account name.
  2. Creation. Create a meeting from a lesson and confirm it appears in your Zoom account.
  3. Webhook. Start and end a short test meeting, then check that your plugin logged the event.
  4. Attendance. Join that test meeting yourself for a minute before ending it, then confirm a participant record was stored.

If step 3 works but step 4 does not, the missing piece is almost always the report:read:list_meeting_participants:admin scope — plus a disconnect and reconnect.

Common errors

“Redirect URI mismatch”

The redirect URL in the Zoom app does not exactly match the one in your plugin. Compare character by character, including protocol and trailing slash.

“Invalid access token” or a scope error

The token predates your scope changes. Disconnect and reconnect.

Webhook validation fails when saving

Zoom must be able to reach your endpoint and receive a correct response. Confirm the plugin is active, the Secret Token is saved in WordPress, and the site is not behind maintenance mode, HTTP authentication, or a firewall rule blocking Zoom.

Meetings are created but nobody completes the topic

Either the participants scope is missing, or meeting.ended is not subscribed. Check both, then disconnect and reconnect.


Skip the guesswork

LiveClass Sync walks you through this setup with the exact URLs and scopes for your site, and includes a health check that tells you which part of the chain is broken.

See plans Read the docs