Requesting Access Token via Python

Description/Error
I want to know how can i request access token for an OAuth App using Python. Do you have a template?
I already have client-id and client-secret. I want to get access token now via Python script which I want to run locally on my machine.
I can successfully generate the token by using "Send a Test Request " feature but now I am looking how to do it using python code.

Hey @nsoni, thanks for posting and using Zoom! :slight_smile:

For server side applications (python) I would suggest using our JWT App Type to generate a JWT Token which you can use without the OAuth flow.

Here is where to find your JWT Token:

You can also generate JWT Tokens with Python.

Then to make requests, set the following auth/headers:

{
   "Authorization": "Bearer JWT_TOKEN_HERE"
}

Let me know if this helps!

Thanks,
Tommy

Thanks @tommy
I have some restrictions around using JWT

Here is my use case: I want to get various webinar related reports via Zoom Api and store the data into our data warehouse. This will be a daily process as we keep on hosting webinars regularly.
Would like to use the following API:

  1. Get Webinar Details: v2/metrics/webinars/{webinarId}
  2. Get Webinar Participants: v2/metrics/webinars/{webinarId}/participants
  3. Get Webinar detail report: v2/report/webinars/{webinarId}

The issue is that I am not an admin user and I have to work with my company’s IT team to get various access. Our IT team is hesitant on providing me JWT credentials as it will give me complete access to this zoom instance. My IT team wants to restrict me to only above Zoom APIs which is possible via defining the Scope section in an OAuth App.
So I think I would have to go ahead with implementing this use case using OAuth. For that purpose can you help me with what will be the steps to be executed using python scripting language.
I am looking for the python version of the Node script in below link:

Or is there any other way I can achieve my use case knowing the constrains I have?
Is OAuth even an option for my use case?

Thanks!

Hey @nsoni,

Thanks for the detailed post.

I agree that a good way to limit complete access is to use only the scopes required for your development with an Account Level OAuth app.

The only challenge I see here, is refreshing the access_token. Does your python script have a way to save the access_token and refresh_token and keep it updated each time you refresh the access_token? If so, then this is a great solution.

Another possible solution, is the Webhook App Type. You can limit which information you receive, and instead of running your python script daily, you can receive webinar data in real time as webinars happen. Although, it may not include all the data you want.

Let me know how you want to move forward, and I can help guide you with the python code.

Thanks,
Tommy

Thanks @tommy
I checked Webhook but they would not work for my use case at they do not have all the information I need.

Here is something I wish to do using Account level OAuth App:

I would schedule a daily job/script that would do the following:

Assuming that I have the Client ID and Client Secret by setting up OAuth App with defined scope.
:
Based on my understanding on how OAuth in Zoom works, My daily script should be able to do the following:

  1. With the help of Client ID and Client Secret, Get Authorization code
  2. With the above details get Access Token (that will last 60 mins)
  3. Make the required API Calls and get the output.

I want to understand how can i achieve step 1 and 2 in python?
Is step 1 needed or can we directly get Access Token with Client ID and Client Secret?
Is it even possible to do above things using OAuth?
Knowing that everyday we will run Step 1 and 2 and my API request would just take seconds to run, do I need to worry about refreshing the access token?

I was able to implement my use case using JWT with the following code on a private account owned by me as I had all admin access:

import sys
sys.path.append(’/users/nsoni/.local/lib/python3.6/site-packages’)
import jwt
import http.client
import datetime
import json

api_key = ‘{Enter API keys}’
api_sec = ‘{ENter API Secret}’

generate JWT

payload = {
‘iss’: api_key,
‘exp’: datetime.datetime.now() + datetime.timedelta(hours=2)
}
jwt_encoded = str(jwt.encode(payload, api_sec), ‘utf-8’)

conn = http.client.HTTPSConnection(“api.zoom.us”)
headers = {
‘authorization’: “Bearer %s” % jwt_encoded,
‘content-type’: “application/json”
}
conn.request(“GET”, “/v2/users/{user_id}/webinars”, headers=headers)
res = conn.getresponse()
response_string = res.read().decode(‘utf-8’)
response_obj = json.loads(response_string)
print(response_obj)

Can I achieve the same using OAuth knowing I cannot get JWT keys from my company’s IT team ?

Thanks!

Hey @nsoni,

Step 1. is a 1 time install process. Once you install / authorize the OAuth app, use the auth code in the url to request an access token.

Step 2. is where your python code will start. It will use the access_token which lasts one hour. Once it expires, you need to use the latest refresh_token to get a new access_token. As long as you can store the updated access_token and refresh_token each time this will work. You could write to a file on the machine that sets and gets the access_token and refresh_token.

Step 3. Get the access_token from the file (or where ever it is saved) and make the respective requests to the Zoom API.

Let me know if that makes sense! :slight_smile:

Thanks,
Tommy

Thanks @tommy

I think the approach makes sense.

  1. Knowing that it is Account Level OAuth app, should the admin be doing Step 1? What are the steps for it? Can step 1 be programmatically or is it possible to do it via UI(by admin or me)?

  2. I see there is a Node.js script provided in the reference documents for doing step 2 (Not taking into account about refreshing token). Is there a python script to achieve step 2 (just generating access token with client ID and Authorization code)?

Thanks!

Hey @nsoni, happy to help!

Yes, someone on your Zoom account that has the permission to install Account Level Apps will do Step 1.

Instructions here:

You have to do it via the UI.

For the Python script, just make an http POST request to:

https://zoom.us/oauth/token?code={{Code_from_Url}}&grant_type=authorization_code&redirect_uri={{Redirect_URL}}

with this Header:

{
   "Authorization": "Basic base64Encode(client_id:client_secret)"
}

Here is how to make an http request in python:

Thanks,
Tommy

Hi @tommy I went ahead with JWT for now, I may switch to OAuth at a later time.

I have another issue right now:

Whenever I use the https://api.zoom.us/v2/report/webinars/{webinarId}/participants API, I get the entire response, however, for the same {webinarId} if I use https://api.zoom.us/v2/metrics/webinars/{webinarId}/participants , I do not get complete response. The value for participant key comes out to be empty.

Code:
conn.request(“GET”, “/v2/reports/webinars/{WebId}/participants”, headers=headers)
res = conn.getresponse()
response_string = res.read().decode(‘utf-8’)
response_obj = json.loads(response_string)
print(response_obj)

Output:
{‘page_count’: 1, ‘page_size’: 30, ‘total_records’: 17, ‘next_page_token’: ‘’, ‘participants’: [{‘id’: ‘xxxx’, ‘user_id’: ‘xxxx’, ‘name’: ‘xxxx’, ‘user_email’: ‘xxxx’, ‘join_time’: ‘xxxx’, ‘leave_time’: ‘xxx’, ‘duration’: xx, ‘attentiveness_score’: ‘xx’},…]}

Code:
conn.request(“GET”, “/v2/metrics/webinars/{WebId}/participants”, headers=headers)
res = conn.getresponse()
response_string = res.read().decode(‘utf-8’)
response_obj = json.loads(response_string)
print(response_obj)

Output:
{‘page_count’: 0, ‘page_size’: 30, ‘total_records’: 0, ‘next_page_token’: ‘’, ‘participants’: }

What could be the reason behind this behavior?

1 Like

Hey @nsoni,

If you are trying to get a previous webinars participants, try setting the ?type=past query param.

If that does not work, try passing in the UUID for as the {WebId}.

Thanks,
Tommy

1 Like

Hi @tommy
type=past worked for above

I have few more questions:
Question 1:
API for getting webinar registrants is not returning constant output.
“/v2/webinars/webinar_id /registrants?page_size=30”

When I run this API for the webinar which happened on Dec 18, 2019, I am getting the expected output mentioned in the API documentation https://marketplace.zoom.us/docs/api-reference/zoom-api/webinars/webinarregistrants

However when I execute the same API for Webinar that happened on Dec 16, 2019 I do not get last_name field in my output. That field is missing all together and rest all fields are present. I also saw that first_name is the concatenation of first_name and last_name for this particular API call.
Why am I getting different output structure?
I can share the webinar_ids over email if you need for debugging.

Question 2:
I am trying to generate the report using Zoom APIs which we can currently download from Zoom UI
via Reports > Usage Reports > Webinar > Attendee Report

There is no single API that helps me get all the below information in the report
The fields under this report are as follows:
Attended - Can you help what would be a good approach for generating this field?
First Name -
Last Name -
Email -
Registration Time -
Approval Status -
Join Time -
Leave Time -
Time in Session (minutes)
Attentiveness Score
Country/Region Name
Source Name - How to get this value via API?

1 Like

Hey @nsoni,

Please create a new topic for this post as it is unrelated to “Request Access Token via Python”.

Thanks,
Tommy

Sure! I will create a new topic

Thanks @nsoni! :slight_smile:

-Tommy

Hi,
I am in the same bus! By looking here and there, I was able to create the following code to get the JWT Token.
-----------------Start Python Code ---------------------
from authlib.jose import jwt
from datetime import timedelta, datetime
from time import mktime, time

def get_jwt_token():
key = ‘************************’
secret = ‘XXXXXXXXXXXXXXXXXXX’
dt = datetime.now()
future = dt + timedelta(seconds=360)
expiration = int(mktime(future.timetuple()))

header = {‘alg’: ‘HS256’, ‘typ’: ‘JWT’}
payload = {‘iss’: key, ‘exp’: expiration}
s = jwt.encode(header, payload, secret)
print(s.decode(“utf-8”))
return s.decode(“utf-8”)

-----------------End Python Code ---------------------
The connection throws an error of “{‘code’: 124, ‘message’: ‘Invalid access token.’}”

I see that the token generated from the web interface had 184 characters and the token generated by this function is 147 char…

Any help resolving this issue…

Hi @jahagirdar.vs here’s a working example using pyjwt:

import jwt
import requests
from time import time

# create a function to generate a token using the pyjwt library
def generateToken():
    token = jwt.encode(
        # Create a payload of the token containing API Key & expiration time
        {"iss": API_KEY, "exp": time() + 5000},
        # Secret used to generate token signature
        API_SECRET,
        # Specify the hashing alg
        algorithm='HS256'
        # Convert token to utf-8
    ).decode('utf-8')

    return token