ZOOM API
Tags: zoom, api, jwt
Published: 2023-07-21 14:29:01

**Note: This is not a step-by-step guide you should have the basic knowledge**
==What this post covers==
1. Replacing Zoom JWT with other zoom apps
2. Adding zoom meetings to your personal account via API
2. Allow Users to join zoom meetings without account through your website 

![Joining through website](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yn037knpq8y9apawag0a.PNG)


I have been busy to update my zoom integration after [JWT App type deprecation](https://developers.zoom.us/docs/internal-apps/jwt-faq/) But 2days before I finally sat down to update it I took me 5HOURS of research just to understand it many many zoom links are broken and thanks to Max M for his clear answers in zoom developer forum

## 1. CREATE ZOOM MEETING API
First You have to create 2 different apps
For creating meeting through API you would have to create a Server-to-Server Oauth By going to [https://marketplace.zoom.us/develop/create](https://marketplace.zoom.us/develop/create) and choosing the Server-to-Server Oauth complete the creation process these are the required scopes to create delete and record meetings and webinars
> View all user meetings /meeting:read:admin
> View and manage all user meetings /meeting:write:admin
> View all user recordings /recording:read:admin
> View and manage all user recordings /recording:write:admin
> View all user Webinars /webinar:read:admin
> View and manage all user Webinars /webinar:write:admin

I did not write this code can't remember where I got it


```
function createAMeeting($data = array()) {
    $post_time           = $data['date'];
    $start_time          = gmdate("Y-m-d\TH:i:s", strtotime($post_time));
    $createAMeetingArray = array();
    if (!empty($data['alternative_host_ids'])) {
        if (count($data['alternative_host_ids']) > 1) {
            $alternative_host_ids = implode(",", $data['alternative_host_ids']);
        } else {
            $alternative_host_ids = $data['alternative_host_ids'][0];
        }
    }
    $createAMeetingArray['topic']      = $data['title'];
    $createAMeetingArray['agenda']     = "";
    $createAMeetingArray['type']       = !empty($data['type']) ? $data['type'] : 2; //Scheduled
    $createAMeetingArray['weekly_days']= [1,2,3,4,5,6,7]; 
    $createAMeetingArray['start_time'] = $start_time;
    $createAMeetingArray['timezone']   = 'SA';
    $createAMeetingArray['password']   = !empty($data['password']) ? $data['password'] : "";
    $createAMeetingArray['duration']   = !empty($data['duration']) ? $data['duration'] : 60;
    $createAMeetingArray['settings']   = array(
        'join_before_host'  => true,
        'host_video'        =>  true,
        'waiting_room'    =>  true,
        'participant_video' => true,
        'mute_upon_entry'   => false,
        'enforce_login'     => false,
        'auto_recording'    => "none",
        'private_meeting'      => true,
        'alternative_hosts' => isset($alternative_host_ids) ? $alternative_host_ids : "",
    );
    return sendRequest($createAMeetingArray);
}
function sendRequest($data){


    $request_url = 'https://api.zoom.us/v2/users/me/meetings';
    $headers     = array(
        'authorization: Bearer ' . generateJWTKey(),
        'content-type: application/json',
    );
    $postFields = json_encode($data);
    $ch         = curl_init();
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_URL, $request_url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    $response    = curl_exec($ch);
    $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $err         = curl_error($ch);
    curl_close($ch);
    if (!$response) {
        return false;
    }
    
    return json_decode($response);
}

function generateJWTKey()
{
    $zoom_api_key    = ZOOM_API_KEY;
    $zoom_api_secret = ZOOM_API_SECRET;

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, 'https://zoom.us/oauth/token');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, "grant_type=account_credentials&account_id={NOT-THE-PROFILE-ID-THE-APP-ID");

    $headers = array();
    $headers[] = 'Host: zoom.us';
    $headers[] = 'Authorization: Basic '.base64_encode($zoom_api_key.':'.$zoom_api_secret);
    $headers[] = 'Content-Type: application/x-www-form-urlencoded';
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

    $result = json_decode(curl_exec($ch));
    if (curl_errno($ch)) {
        echo 'Error:' . curl_error($ch);
    }
    curl_close($ch);
    
    return $result->access_token;`
}
```
## 2. Join From Web SDK
Navigate back to the create app choose meeting SDK and go through the steps 
Do not forget to download the sample code and this is as I believe a more explanatory page 

```
<?php

    use \Firebase\JWT\JWT;

    //Validate if user is allowed to join



    function generate_signature($sdkKey, $sdkSecret, $meetingNumber, $role) {
        $iat = time();
        $exp = $iat + 60 * 60 * 2;
        
        $token_payload = [
          "sdkKey"=> $sdkKey,
          "mn"=> $meetingNumber,
          "role"=> $role,
          "iat"=> $iat,
          "exp"=> $exp,
          "tokenExp"=> $exp
        ];
        $token_header = [
          'alg'=> 'HS256',
          'typ'=> 'JWT'
        ];
        $jwt = JWT::encode($token_payload, $sdkSecret);
        
        return $jwt;
    }
    
?>


<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>{YOUR_TITLE}</title>

    <!-- For Client View -->
    <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.14.0/css/bootstrap.css" />
    <link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.14.0/css/react-select.css" />
    <link rel="shortuct icon" type="image/png" href="favicon url">
    <link rel="stylesheet" href="styles.css">

    <!-- Origin Trials to enable Gallery View in Chrome/Edge -->
    <!-- More Info: https://developers.zoom.us/docs/meeting-sdk/web/gallery-view/ -->
    <!-- SharedArrayBuffers in non-isolated pages on Desktop platforms -->
    <meta https-equiv="origin-trial" content="">
  </head>
  <body>

    <main>
      <h1>Processing View...</h1>

      <!-- For Component View -->
      <div id="meetingSDKElement">
        <!-- Zoom Meeting SDK Rendered Here -->
      </div>

    </main>

    <!-- For Component and Client View -->
    <script src="https://source.zoom.us/2.14.0/lib/vendor/react.min.js"></script>
    <script src="https://source.zoom.us/2.14.0/lib/vendor/react-dom.min.js"></script>
    <script src="https://source.zoom.us/2.14.0/lib/vendor/redux.min.js"></script>
    <script src="https://source.zoom.us/2.14.0/lib/vendor/redux-thunk.min.js"></script>
    <script src="https://source.zoom.us/2.14.0/lib/vendor/lodash.min.js"></script>

    <!-- For Client View -->
    <script src="https://source.zoom.us/zoom-meeting-2.14.0.min.js"></script>
    <!-- <script type="text/javascript" src="client-view.js"></script> -->
    <script>
      ZoomMtg.setZoomJSLib('https://source.zoom.us/2.14.0/lib', '/av')

      ZoomMtg.preLoadWasm()
      ZoomMtg.prepareWebSDK()
      // loads language files, also passes any error messages to the ui
      ZoomMtg.i18n.load('en-US')
      ZoomMtg.i18n.reload('en-US')

      var authEndpoint = ''
      var sdkKey = '<?= ZOOM_SDK_KEY ?>'
      var role = 0
      var userEmail = ''
      var registrantToken = ''
      var zakToken = ''
      var leaveUrl = '<?= $leaveUrl ?>'
      var meetingNumber = '<?= $meetingID ?>'
      var userName = '<?= $name ?>'
      var passWord = '<?= $room_password ?>'
      var signature = '<?= generate_signature(ZOOM_SDK_KEY, ZOOM_SDK_SECRET, $meetingID, $role); ?>'
      

        document.getElementById('zmmtg-root').style.display = 'block'

        ZoomMtg.init({
          leaveUrl: leaveUrl,
          success: (success) => {
            console.log(success)
            ZoomMtg.join({
              sdkKey: sdkKey,
              signature: signature,
              meetingNumber: meetingNumber,
              passWord: passWord,
              userName: userName,
              success: (success) => {
                console.log(success)
              },
              error: (error) => {
                console.log(error)
              },
            })
          },
          error: (error) => {
            console.log(error)
          }
        })

    </script>
  </body>
</html>
```

The hardest part was not the code it was understanding what I am supposed to do and what apps to create wish this will save someone's time comment if any issues appear
resources:
[Create Zoom Meeting API Docs](https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#operation/meetingCreate)
[Zoom Developer Forum](https://devforum.zoom.us/)