Best app type for third-party integration S2S vs General App (user-level scopes needed)

We’re a third-party partner (Boltflow) building an Airtable ↔ Zoom integration for a university client and we need guidance on how to proceed given the following:

  • The customer does not want to grant our team admin-level access on their Zoom account

  • The integration needs to: (1) create meetings on behalf of specific users, and (2) receive recording.completed webhooks

  • We originally planned for Server-to-Server OAuth but understand it requires admin-level scopes

  • We’re evaluating whether a General App with user-level scopes is the right path, and if so, what the token management requirements look like

What’s the recommended app type and scope configuration for a non-admin third-party integration that creates meetings and captures recordings?

Hi @AndresBoltflow, thanks for the detailed breakdown - here is exactly what you need.

App Type: General App (User-Level OAuth)

Server-to-Server OAuth requires admin access and is internal-only. General App with user-level OAuth is the right call for your setup. One important thing to note is that you will need to build and publish your app on the Zoom Marketplace for external users outside your account to authorize and use it. Until published, the app only works for users within your own developer account.

Scopes

meeting:write:meeting for creating meetings, cloud_recording:read:recording for the recording.completed webhook and downloading/syncing recordings, user:read:user and meeting:read:meeting for basic user and meeting data.

Token Management

Each user authorizes individually through the OAuth flow. You get an access token and a refresh token per user, both stored in your DB. Access tokens expire in 1 hour so auto-refresh using the refresh token and update both tokens in your DB on each refresh. Refresh tokens expire in 90 days if unused, so either silently refresh them via a background job before expiry, or prompt the user to re-authorize if the refresh token has already expired.

Webhooks

Bind recording.completed at the app level and it covers all authorized users automatically. Use the client_credentials grant type for webhook authentication. With cloud_recording:read:recording already in your scopes, you can also download and sync recordings programmatically in the same flow.

Hope this clears things up and helps you move forward with the integration. If you have any further queries feel free to ask. Thanks!

Thanks,
Naeem Ahmed

We’ll be doing this using Zoom Rooms (which we’re unfamiliar with) and our understanding is that each Zoom Room will have a dedicated Zoom account that will be logged into as the host of the meeting. In this case, are these Zoom Room accounts the users that will be authorized? Are there any unique considerations we need to be aware of for this use case?