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!
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:
- Get Webinar Details: v2/metrics/webinars/{webinarId}
- Get Webinar Participants: v2/metrics/webinars/{webinarId}/participants
- 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:
- With the help of Client ID and Client Secret, Get Authorization code
- With the above details get Access Token (that will last 60 mins)
- 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!
Thanks,
Tommy
Thanks @tommy
I think the approach makes sense.
-
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)?
-
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:
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?
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
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?
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
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