OAuth with Zoom


Below are examples of how to send requests for Access Tokens and handle responses for OAuth app authentication and authorization with Zoom APIs, products, and SDKs.

Authorization Code

Once you have your app credentials, you can use your Client ID to request an authorization code. This is not the final code that will be used to request user data - it will be used in the next step to authenticate a request for the access token.

Authorization endpoint

The authorization endpoint is where the end-user is authenticated and also where the end-user provides your app with the authorization grant to have access to the requested scopes. Your app must direct the end-user to Zoom’s authorize endpoint with client credentials to request an authorization code. When the user authorizes your app with access permissions, Zoom’s API server authenticates the user and directs the user back to your app along with an authorization code.

Start by sending your user to the Authorization URL. This is either provided in your app details page on the marketplace or it back be built manually using the following formula:

response_type=code 
client_id={clientID} // auto-generated when you register your app in the marketplace
redirect_uri={redirect_uri} 

Sample request

https://zoom.us/oauth/authorize?response_type=code&client_id={YOUR_CLIENT_ID}&redirect_uri={https://YOUR_REDIRECT_URI}

NOTE: The redirect_uri needs to be on your app’s whitelist in order to complete the OAuth transaction.

There are additional parameters that can be passed along with the request. The entire list of Available Parameters is shown below:

Parameter Description Required
response_type This is the authorization type. In this case, it should be set to code. Yes
client_id The identifier issued to the client during the registration process. Yes
redirect_uri Your app’s url to which Zoom redirects the user with the authorization code or an error response code. This must match one of the redirect URIs used during registration. Yes
state An optional string passed with the request to prevent CSRF. The state will be sent back when the redirect occurs to ensure that you initiated the request.
e.g. state=DH73HL9123hfk873g
Optional
scope A URL encoded the string of scopes you’re requesting for your app on behalf of the user. If you do not provide this during the request, we will fallback to the scopes you defined during your application registration.
e.g. scope=user%3Aread+meeting%3Awrite+webinar%3Awrite
Optional

Sample Node Request

const zoomclientid = "enter your client id";
const myappredirect = "https://myapp.io/zoomcallback"; 
const zoomauth = "https://zoom.us/oauth/authorize" + "?response_type=code&client_id=" + zoomclientid + "&redirect_uri=" + myappredirect; 
res.redirect(zoomurl);

If this is the first time that you are requesting authorization from a user, the user will be directed to Zoom’s authorization page. Once the user allows your app to access their account, the user will be redirected to the URI that you have set up as the redirect_uri.

If the user has previously authorized your app with access and if the authorization is still valid, the authorization screen will be immediately bypassed and the user will be redirected to your redirect_uri. Zoom will return a 200 OK response header if your Client ID and redirect URI match with what you have registered when creating the app in our marketplace.
If you get a 400 or a 401 error, check your Client ID and redirect URI again to make sure they match with what has been registered in the Zoom marketplace.

Zoom will trigger a callback to the redirect URIthat you previously registered. The callback will have the authorization code that you have requested in the above step. This code will be attached as a query string in the redirect URI as shown below:
https://myapp.com/oauth/?code=eYanu1uG5TucLenI
This code will be used in the next step to request the access token to allow your app to make requests on behalf of the user. If you sent a state value with the original request, this will also be sent back and can be used to test for CSRF attacks. If the value provided in the state parameter does not match with the response state, the request is immediately denied for security purposes and you will receive a 401 error message.

Request an Access Token

Once you have the authorization code, you can now make a request for an access token. This is the token that you will use to make subsequent requests on behalf of the authorized user.

Access Token Endpoint

Make a POST request to https://zoom.us/oauth/token endpoint. Include the following query parameters along with your requests:

Parameter Value
grant_type authorization_code
code {your_authorization_code}
redirect_uri {your_redirect_uri}

Additionally, you should include the following in the authorization header:
"Authorization" : "Basic base64(client_id:client_secret)"

Sample Node Request

router.get('/zoomcallback', function(req, res) {

    const zoomtokenep = "https://zoom.us/oauth/token";
    const myappredirect = "https://myapp.io/zoomcallback";

    if (req.query.code) {
        var auth = "Basic " + new Buffer(zoomclientid + ':' +
            zoomclientsec).toString('base64');
        var url = zoomtokenep + '?grant_type=authorization_code&code=' +
            req.query.code + '&redirect_uri=' + myappredirect;
        request.post({
            url: url,
            headers: {
                "Authorization": auth
            }
        }, function(error, response, body) {
            if (error) {
                console.log("Error when getting Zoom token = " + error);
                return;
            }
            body = JSON.parse(body);
            if (body.access_token) {
                accessToken = body.access_token;
                refreshToken = body.refresh_token;
                // Process and securely store these tokens
            } else {
                console.log("FATAL - could not get zoom token");
            }
            return;
        });

    } else {
        console.log("Missing code from Zoom");
    }
});

Evaluate Access Token Response

If the request is successful, a JSON response will be returned. This JSON object will have all the information you need to complete requests and to request additional tokens once the initial access token expires.
The following response parameters will be returned:

Parameter Description
access_token The token you will use to make requests on behalf of the user.
token_type The type of token that will be sent to make requests.
refresh_token Used when requesting a new access token once the previous one has expired.
expires_in Time in seconds until the access token expires. Once expired you will use the refresh token to request a new access token.
scope A space-delimited string of available scopes associated with your app for the access token.

Example Response Schema

{
  "access_token": "5kwaMOrdEFWx1jYVK8qg80cImPYBA83Zff",
  "token_type": "bearer",
  "refresh_token": "Ggf2816C5ANa6XVplzO8vwE6IRIXtjvE",
  "expires_in": 3599,
  "scope": "meeting:write user:read recording:write webinar:write"
}

Refresh Access Token

The original access token expires in 60 minutes. If you call a Zoom API with an expired access token, you will receive an invalid 400 or 401 error. If you need to make additional API calls after the initial access token expires, you will need to refresh your access token. You can do this by setting the value of grant_type to refresh_token and using the refresh_token parameter with the refresh_token string instead of code.

Sample cURL Request for Refresh Token

curl -X POST -H "Content-Type:application/x-www-form-urlencoded" \
--user client_id:client_secret  \
--data 'grant_type=refresh_token&refresh_token={refresh_token}' \
https://zoom.us/oauth/token

Refresh Token Response Example

{
  "access_token": "eyJhbGciOiJIUzUxMiJ9",
  "token_type": "bearer",
  "refresh_token": "eyJhbGciOiJIUzUxMiJ9",
  "expires_in": 3599,
  "scope": "imchat:write"
}
Refresh Tokens

Refresh Tokens have a lifespan of 15 years. When you refresh an access token, you will also get a new refresh token that you need to use in your next refresh. Store the new refresh token safely for the next time when you try to refresh the tokens.

Example Node Refresh Token Request

function refresh_token(refreshToken, freshToken, zoomclientid, zoomclientsec, myappredirect) {

    const zoomtokenep = "https://zoom.us/oauth/token";

    var auth = "Basic " + new Buffer(zoomclientid + ':' +
        zoomclientsec).toString('base64');
    var url = zoomtokenep + '?grant_type=refresh_token&refresh_token='+ refreshToken + 
    '&redirect_uri=' + myappredirect;
    request.post({
        url: url,
        headers: {
            "Authorization": auth
        }
    }, function(error, response, body) {
        if (error) {
            console.log("Error when getting Zoom token = " + error);
            return;
        }
        body = JSON.parse(body);
        if (body.access_token) {
            console.log("Got new access and refresh tokens");
            accessToken = body.access_token;
            refreshToken = body.refresh_token;
            // Process and securely store these tokens
        } else {
            console.log("FATAL - could not refresh access token");
        }
        return;
    });
}

Revoke Access Token

In some scenarios where the user wishes to revoke your app’s access or when you need to revoke the access yourself, you will have to revoke the access tokens.
To do so, make a POST request to Zoom revoke endpoint as shown below:
POST https://zoom.us/oauth/revoke
The POST request must include the following parameters:

Header: Content-Type':'application/x-www-form-urlencoded’
Body: token=<TOKEN>

Provide your current access token that is valid and not expired. Provide your Client ID in the user field and the Client Secret in the pass field as the password as shown in the example below:

Example Node Revoke Access Token

var request = require('request');

var headers = {
    'Content-Type': 'application/x-www-form-urlencoded'
};

var dataString = 'token=04WRoU4vb9cK1l8Ne8okytrJSvsZx0J8';

var options = {
    url: 'https://zoom.us/oauth/revoke',
    method: 'POST',
    headers: headers,
    body: dataString,
    auth: {
        'user': 'Odet7ldYQjyagzLKzNomA',
        'pass': 'UeE0e7LZopJRFityw1h3b7dJFz29IeY7'
    }
};

function callback(error, response, body) {
    if (!error && response.statusCode == 200) {
        console.log(body);
    }
}

request(options, callback);


The /me context

For some Zoom API calls where you use OAuth, you can use me in place of the User ID to restrict the context of the call to the user that token belongs to. This is a shortcut when using user-specific endpoints instead of needing to lookup/store the user ID for each token.

Below is a list of all URLs that support me:

Method URL(v2)
GET /v2/users/me
PATCH /v2/users/me
GET /v2/users/me/settings
PATCH /v2/users/me/settings
GET /v2/users/me/assistants
POST /v2/users/me/assistants
DELETE /v2/users/me/assistants
DELETE /v2/users/me/assistants/{assistantId
GET /v2/users/me/token
DELETE /v2/users/me/token
GET /v2/users/me/meetings
POST /v2/users/me/meetings
GET /v2/users/me/webinars
POST /v2/users/me/webinars
GET /v2/users/me/recordings

For all other object definitions please see our API Reference.


Next Steps

You have now successfully learned how to authenticate your app with Zoom on behalf of your user! Move on to our Quickstart - OAuth guide, or check out our Sample OAuth App on GitHub.

Need Support?

The first place to look for help is on our Developer Forum, where Zoom Marketplace Developers can ask questions for public answers.

If you can’t find the answer in the Developer Forum or your request requires sensitive information to be relayed, please email us at developersupport@zoom.us.