Using Add Panelists EndPoint

Hello,

I am trying to follow the documentation on how to use your api, to add panelists to a webinar.
I am working with an excel file provided by one of the organizers. The file contains a list of names and email addresses.
I want to create a web form that the user can use to upload the excel file, then programmatically take the excel data and convert it into an array to pass to your panelists endpoint so that the panelists can be added via this form rather than having to enter one by one by the webinar organizer.

I visited this URL: https://marketplace.zoom.us/docs/api-reference/zoom-api/webinars/webinarpanelistcreate

At the bottom of the page, there is a form to request an access token, I provide the webinar id, then click on the get access token button, and a modal window pops up.
In this window I am asked to provide the client id, and client secret plus the auth and token urls that are already populated.

After I do this, I do obtain the access token. And can see the generated code:

var data = excelData; <- I would pass my array with the excel data here
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener(“readystatechange”, function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}});
xhr.open(“POST”, “https://api.zoom.us/v2/webinars/943%209575%203143/panelists”); <- call zoom panelists endpoint
xhr.setRequestHeader(“content-type”, “application/json”);
xhr.setRequestHeader(“authorization”, “Bearer eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiIxMDU2ZGY2Ny0yNjhiLTQ4MjktODdmYi1jMjJlODNhNDA3NzkifQ.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiJYaU1ZZGhQUjI2ZFZHS2U4ODNYY3ciLCJjb2RlIjoiT1lIZHdUN0h5cF9MOEY5U1pWSVRWV0k5dE40cVBDX0pBIiwiaXNzIjoidXJuOnpvb206Y29ubmVjdDpjbGllbnRpZDpYaU1ZZGhQUjI2ZFZHS2U4ODNYY3ciLCJhdXRoZW50aWNhdGlvbklkIjoiYWQ0ZmU4YzQ3ZWQxZjk3ODE3ZDc5MDdlOWUzM2M4MTQiLCJ1c2VySWQiOiJMOEY5U1pWSVRWV0k5dE40cVBDX0pBIiwiZ3JvdXBOdW1iZXIiOjAsImF1ZCI6Imh0dHBzOi8vb2F1dGguem9vbS51cyIsImFjY291bnRJZCI6IlpTSk9iYnk5UkUyLXZuQWF5U3c0WkEiLCJuYmYiOjE1OTIyNTMwNDAsImV4cCI6MTU5MjI1NjY0MCwidG9rZW5UeXBlIjoiYWNjZXNzX3Rva2VuIiwiaWF0IjoxNTkyMjUzMDQwLCJqdGkiOiJiMWI3NjhjZC02OTVjLTQwMzYtOTQwNC1mMjUwN2NkZTc0NTIiLCJ0b2xlcmFuY2VJZCI6MH0.X-a5hlSEs7hCc–8kGTh8mW-NtlDTUfOswhErHwAvVa251MQVJ5PdxLh7v1B-B4qNC25B3NH5IZOvrNeK0AATg”);

xhr.send(data)

My question is, what keys would I have to provide when I call your end point via my web app (combination of JavaScript and C#/ASP.Net) In the generated code, I only see webinar id, and what you refer to as “Bearer” which I am assuming is the access token that I generated previously. Will I also need to provide the Client ID, Client Secret, Authorize URL, Access Token URL, Client Authentication?

Will I have to create an access token each time I want to run my web app to process a new list of panelists (excel)?

The documentation is not clear about these steps, at least not for me.

Are you able to provide some direction that will allow me to continue my development of this web app?

Hey @elamsupport,

Good question, there are two ways to make authenticated requests to the Zoom API in this case.

  1. Using a JWT token which you can generate each time before you make an API request.

  2. Using an OAuth token, which you will need to store and refresh tokens.

I would suggest using JWT since this seems to be an internal integration.

Let me know if you have additional questions! :slight_smile:

Thanks,
Tommy

Hi Tommy,

I am at the point that I can add the auto generated code to my web application and run a few tests.

This web app is an angularJS app.

When I get to the POST part of the code:
xhr.open(“POST”, “https://api.zoom.us/v2/webinars/” +$scope.webinarId + “/panelists”);
xhr.setRequestHeader(“content-type”, “application/json”);
xhr.setRequestHeader(“authorization”, "Bearer ");
xhr.send(data_panelists);

I get the following error:

What else do I need to specify?
Do I have to whitelist my localhost url?

Hey @elamsupport,

You cannot call the Zoom API from the client side (frontend). You need to make requests server side (backend) or else you will run into CORS errors.

Thanks,
Tommy

Hi Tommy,

Thank you for the reply.

I am now using .Net/C# to implement the post http request.
Your auto generated code looks something like this:

var client = new RestClient(“https://api.zoom.us/v2/webinars/123456/panelists”);
var request = new RestRequest(Method.POST);
request.AddHeader(“content-type”, “application/json”);
request.AddHeader(“authorization”, “Bearer access_token”);
request.AddParameter(“application/json”, “{“panelists”:[{“name”:“Mary”,“email”:“maryjkdfdsgfshdgf@jdfdkjdglfk.jkfgdj”},{“name”:“Mike”,“email”:“dfdsgfsdhf@jkgfdgfkdhgfdjg.fkjgdf”}]}”, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

I have installed the nuget packages RestSharp Version 106.11.4.0, and RestClient.Version 2.4.4.21

I am having problems with RestClient, I get the error:
RestClient’ is a namespace but is used like a type

restClient_error

Do you have any idea why this might be happening?

Thank you,
Alejandro

I think I need to do RestSharp.RestClient in order to access the client.

Hey @tommy - I implemented the auto generated code, ran it a few times using a hard coded access token for my tests, I am aware that a refresh token functionality is also needed.

I am getting a response of 0

This is my code:

public void CreatePanelists (Newtonsoft.Json.Linq.JObject data)
{

        Parameters parameters = JsonConvert.DeserializeObject<Parameters>(data.ToString());

        IList<Panelist> panelistList = parameters.panelists;
        string id = parameters.id;

        var client = new RestSharp.RestClient("https://api.zoom.us/v2/webinars/" + id +"/panelists");
        var request = new RestRequest(Method.POST);
        request.AddHeader("Accept", "application/json");
        request.AddHeader("Content-Type", "application/json");
        request.AddHeader("authorization", "Bearer access_token");
        request.AddParameter("application/json", "{\"panelists\":[{\"name\":\"Mary\",\"email\":\"maryjkdfdsgfshdgf@jdfdkjdglfk.jkfgdj\"},{\"name\":\"Mike\",\"email\":\"dfdsgfsdhf@jkgfdgfkdhgfdjg.fkjgdf\"}]}", ParameterType.RequestBody);
        IRestResponse response = client.Execute(request);
        var content = response.Content;

    }

Hey @elamsupport,

What error message are you getting?

Thanks,
Tommy

Hi @tommy,

I am not getting an error, I get a response code of 0 and content is empty.
I am trying to add panelists to a webinar using the code I shared above.

Hey @elamsupport,

I just tested in Postman and it worked:

Request Body:

{
  "panelists": [
    {
      "name": "Mary",
      "email": "maryjkdfdsgfshdgf@jdfdkjdglfk.jkfgdj"
    },
    {
      "name": "Mike",
      "email": "dfdsgfsdhf@jkgfdgfkdhgfdjg.fkjgdf"
    }
  ]
}

Response Body:

{
    "id": "***********",
    "updated_at": "2020-06-30T22:45:33Z"
}

Double check you are sending the request body properly.

Thanks,
Tommy

*This post has been edited to remove any meeting / webinar IDs

Hi @tommy -

I am sending hard codes values, following the example from the code generated:

        var client = new RestSharp.RestClient("https://api.zoom.us/v2/webinars/" + id +"/panelists");
        var request = new RestRequest(Method.POST);
        request.AddHeader("content-type", "application/json");
        request.AddHeader("authorization", "Bearer eyJhbGciOiJIUzUxMiIsInYiOiIyLjAiLCJraWQiOiJkMDk4NjY5Yi1hM2Q1LTQzMjAtYmY5OC00OTZjMzc0OTBkOWQifQ.eyJ2ZXIiOiI2IiwiY2xpZW50SWQiOiJYaU1ZZGhQUjI2ZFZHS2U4ODNYY3ciLCJjb2RlIjoibkc2Uk1KMjVWQ19MOEY5U1pWSVRWV0k5dE40cVBDX0pBIiwiaXNzIjoidXJuOnpvb206Y29ubmVjdDpjbGllbnRpZDpYaU1ZZGhQUjI2ZFZHS2U4ODNYY3ciLCJhdXRoZW50aWNhdGlvbklkIjoiYWQ0ZmU4YzQ3ZWQxZjk3ODE3ZDc5MDdlOWUzM2M4MTQiLCJ1c2VySWQiOiJMOEY5U1pWSVRWV0k5dE40cVBDX0pBIiwiZ3JvdXBOdW1iZXIiOjAsImF1ZCI6Imh0dHBzOi8vb2F1dGguem9vbS51cyIsImFjY291bnRJZCI6IlpTSk9iYnk5UkUyLXZuQWF5U3c0WkEiLCJuYmYiOjE1OTM1MzAzNzYsImV4cCI6MTU5MzUzMzk3NiwidG9rZW5UeXBlIjoiYWNjZXNzX3Rva2VuIiwiaWF0IjoxNTkzNTMwMzc2LCJqdGkiOiJiZWFjNjFmMC0wMWJlLTQyZjctYTdlZi03YjhmNWNiZTA4MjgiLCJ0b2xlcmFuY2VJZCI6MH0.c0nCVFehwDP4xRLLjTY3MunhF47hzmihrzKwSNoVoc97qnOyCYzA9akdhzUYjRiQoymPxvKwYpNn3c-nA0EMtg");
        request.AddParameter("application/json", "{\"panelists\":[{\"name\":\"Alejandro\",\"email\":\"anava-gomez@cityofmadison.com\"},{\"name\":\"Riki\",\"email\":\"rsjachrani@cityofmadison.com\"}]}", ParameterType.RequestBody);
        IRestResponse response = client.Execute(request);
        var content = response.Content;

Hey @elamsupport,

Did that work?

Thanks,
Tommy

@tommy - No it’s not working yet. I still get response code 0, and content is empty.

not sure what I am doing wrong.

Thank you,
Alejandro

Hey @elamsupport,

Can you please try making this request on our docs, or on Postman to see if it works? I wonder if it is an issue with your code.

Thanks,
Tommy

Hi @tommy -

I am able to successfully do a post request. The issue: since I am using .Net 4.0, and https, I needed to set the security protocol prior to the initialization of the RestSharp client:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

The error I was getting:

The underlying connection was closed: An unexpected error occurred on a send.

Did some research and found information that helped me correct it.

If I can make a suggestion, consider adding that line when the generated code is C#. It would save a considerable amount of research time, when trying to implement your code in a custom web app.

Thank you,
Alejandro

1 Like

@tommy - In case that someone needs a C# example, this is the version of my code that successfully post a list of panelists to a webinar:

    [HttpPost]
    public string CreatePanelists([FromBody] Parameters parameters)
    {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

        var webId = parameters.id;
        var jwt_token = JWTToken.GetJWTToken();
        var panelists = JsonConvert.SerializeObject(parameters.panelists);
        var client = new RestSharp.RestClient($"https://api.zoom.us/v2/webinars/{webId}/panelists");
        var request = new RestRequest(Method.POST);

        request.AddHeader("content-type", "application/json");
        request.AddHeader("authorization", $"Bearer {jwt_token}");
        request.AddParameter("application/json", $"{{\"panelists\": {panelists}}}", ParameterType.RequestBody);
        IRestResponse response = client.Execute(request);
       
        return response.Content;

    }

The code to generate a JWT Token:

    public static string GetJWTToken()
    {
        // Token will be good for 20 minutes
        DateTime Expiry = DateTime.UtcNow.AddMinutes(20);

        string ApiKey = "your api key";
        string ApiSecret = "your api secret";

        int ts = (int)(Expiry - new DateTime(1970, 1, 1)).TotalSeconds;

        // Create Security key  using private key above:
        var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(Encoding.UTF8.GetBytes(ApiSecret));

        // length should be >256b
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

        //Finally create a Token
        var header = new JwtHeader(credentials);

        //Zoom Required Payload
        var payload = new JwtPayload
    {
        { "iss", ApiKey},
        { "exp", ts },
    };

        var secToken = new JwtSecurityToken(header, payload);
        var handler = new JwtSecurityTokenHandler();

        // Token to String so you can use it in your client
        var tokenString = handler.WriteToken(secToken);

        return tokenString;
    }

Thank you,
Alejandro

1 Like

Hey @elamsupport,

Happy to hear you got it working! :slight_smile:

Thanks for your feedback and suggestion, we will look into adding that line to our docs! CC @shrijana.g

-Tommy