Top of pageSkip to main content

Generate signature


JWT app type

See the following instructions to generate your signature using your JWT app type key and secret.

JWT signature parameters

NameDescription
apiKeyRequired, your JWT API key
apiSecretRequired, your JWT API secret
meetingNumberRequired, the Zoom meeting or webinar number.
roleRequired, 0 to specify participant, 1 to specify host.

Signature code samples


const crypto = require('crypto') // crypto comes with Node.js
function generateSignature(apiKey, apiSecret, meetingNumber, role) {
  // Prevent time sync issue between client signature generation and Zoom
  const timestamp = new Date().getTime() - 30000
  const msg = Buffer.from(apiKey + meetingNumber + timestamp + role).toString('base64')
  const hash = crypto.createHmac('sha256', apiSecret).update(msg).digest('base64')
  const signature = Buffer.from(apiKey, meetingNumber, timestamp, role, hash).toString('base64')
  return signature
}
// pass in your Zoom JWT API key, Zoom JWT API secret, Zoom meeting number, and 0 to join meeting or webinar or 1 to start meeting
console.log(generateSignature(process.env.API_KEY, process.env.API_SECRET, 123456789, 0))

function generate_signature ( $api_key, $api_secret, $meeting_number, $role){
  //Set the timezone to UTC
  date_default_timezone_set("UTC");
	$time = time() * 1000 - 30000;//time in milliseconds (or close enough)
	$data = base64_encode($api_key . $meeting_number . $time . $role);
	$hash = hash_hmac('sha256', $data, $api_secret, true);
	$_sig = $api_key . "." . $meeting_number . "." . $time . "." . $role . "." . base64_encode($hash);
	//return signature, url safe base64 encoded
	return rtrim(strtr(base64_encode($_sig), '+/', '-_'), '=');
}

import hashlib
import hmac
import base64
import time
def generateSignature(data):
    ts = int(round(time.time() * 1000)) - 30000;
    msg = data['apiKey'] + str(data['meetingNumber']) + str(ts) + str(data['role']);
    message = base64.b64encode(bytes(msg, 'utf-8'));
    # message = message.decode("utf-8");
    secret = bytes(data['apiSecret'], 'utf-8')
    hash = hmac.new(secret, message, hashlib.sha256);
    hash =  base64.b64encode(hash.digest());
    hash = hash.decode("utf-8");
    tmpString = "%s.%s.%s.%s.%s" % (data['apiKey'], str(data['meetingNumber']), str(ts), str(data['role']), hash);
    signature = base64.b64encode(bytes(tmpString, "utf-8"));
    signature = signature.decode("utf-8");
    return signature.rstrip("=");
if __name__ == '__main__':
    data = {'apiKey': "" ,
                'apiSecret': "",
                'meetingNumber': 888,
                'role': 0}
	print (generateSignature(data))

import hashlib
import hmac
import base64
import time
def generateSignature(data):
    ts = int(round(time.time() * 1000)) - 30000;  #ts; // 1544683367752
    print (ts)
    msg = data['apiKey'] + str(data['meetingNumber']) + str(ts) + str(data['role']);
    message = base64.b64encode(bytes(msg).encode('utf-8'));
    secret = bytes(data['apiSecret']).encode('utf-8')
    hash = hmac.new(secret, message, hashlib.sha256);
    hash =  base64.b64encode(hash.digest());
    hash = hash.decode("utf-8");
    tmpString = "%s.%s.%s.%s.%s" % (data['apiKey'], str(data['meetingNumber']), str(ts), str(data['role']), hash);
    signature = base64.b64encode(bytes(tmpString).encode("utf-8"));
    signature = signature.decode("utf-8");
    return signature.rstrip("=");
if __name__ == '__main__':
    data = {'apiKey': "" ,
                'apiSecret': "",
                'meetingNumber': 8998,
                'role': 0}
    print (generateSignature(data))

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.security.InvalidKeyException;
import javax.xml.bind.DatatypeConverter;
public class test {
	public static String generateSignature(String apiKey, String apiSecret, String meetingNumber, Integer role) {
		try {
			Mac hasher = Mac.getInstance("HmacSHA256");
			String ts = Long.toString(System.currentTimeMillis() - 30000);
			String msg = String.format("%s%s%s%d", apiKey, meetingNumber, ts, role);
			hasher.init(new SecretKeySpec(apiSecret.getBytes(), "HmacSHA256"));
			String message = Base64.getEncoder().encodeToString(msg.getBytes());
			byte[] hash = hasher.doFinal(message.getBytes());
			String hashBase64Str = DatatypeConverter.printBase64Binary(hash);
			String tmpString = String.format("%s.%s.%s.%d.%s", apiKey, meetingNumber, ts, role, hashBase64Str);
			String encodedString = Base64.getEncoder().encodeToString(tmpString.getBytes());
			return encodedString.replaceAll("\=+$", "");
	  	}
	  	catch (NoSuchAlgorithmException e) {}
	  	catch (InvalidKeyException e) {}
		return "";
	}
	public static void main(String[] args) {
		String signature = test.generateSignature("apiKey", "apiSecret", "meetingNumber", 0);
		System.out.println(signature);
	}
}

// this demo use vscode and .NET Core 2.2.5
// https://docs.microsoft.com/en-us/dotnet/core/tutorials/with-visual-studio-code
// https://dotnet.microsoft.com/download
// dotnet add package Microsoft.IdentityModel.Tokens
// dotnet add package System.IdentityModel.Tokens.Jwt
// https://www.red-gate.com/simple-talk/dotnet/net-development/jwt-authentication-microservices-net/
// https://www.jokecamp.com/blog/examples-of-creating-base64-hashes-using-hmac-sha256-in-different-languages/#csharp
// https://marketplace.zoom.us/docs/sdk/native-sdks/Web-Client-SDK/tutorial/generate-signature
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using Microsoft.IdentityModel.Tokens;
namespace Zoom {
    class Program {
        static readonly char[] padding = { '=' };
        static void Main (string[] args) {
            Console.WriteLine ("Zoom copyright!");
            Console.WriteLine ("generate websdk token!");
            string apiKey = "apiKey";
            string apiSecret = "apiSecret";
            string meetingNumber = "";
            String ts = (ToTimestamp(DateTime.UtcNow.ToUniversalTime()) - 30000).ToString();
            string role = "1";
            string token = GenerateToken (apiKey, apiSecret, meetingNumber, ts, role);
            Console.WriteLine (token);
        }
        public static long ToTimestamp (DateTime value) {
            long epoch = (value.Ticks - 621355968000000000) / 10000;
            return epoch;
        }
        public static string GenerateToken (string apiKey, string apiSecret, string meetingNumber, string ts, string role) {
            string message = String.Format ("{0}{1}{2}{3}", apiKey, meetingNumber, ts, role);
            apiSecret = apiSecret ?? "";
            var encoding = new System.Text.ASCIIEncoding ();
            byte[] keyByte = encoding.GetBytes (apiSecret);
            byte[] messageBytesTest = encoding.GetBytes (message);
            string msgHashPreHmac = System.Convert.ToBase64String (messageBytesTest);
            byte[] messageBytes = encoding.GetBytes (msgHashPreHmac);
            using (var hmacsha256 = new HMACSHA256 (keyByte)) {
                byte[] hashmessage = hmacsha256.ComputeHash (messageBytes);
                string msgHash = System.Convert.ToBase64String (hashmessage);
                string token = String.Format ("{0}.{1}.{2}.{3}.{4}", apiKey, meetingNumber, ts, role, msgHash);
                var tokenBytes = System.Text.Encoding.UTF8.GetBytes (token);
                return System.Convert.ToBase64String (tokenBytes).TrimEnd (padding);
            }
        }
    }
}

Simple signature setup

To quickly, easily, and securely generate a signature for the Meeting SDK, check out the Signature Sample App.


Once you have a signature, choose a view, then start and join Zoom meetings and webinars.

Need help?

If you're looking for help, try Developer Support or our Developer Forum. Priority support is also available with Premier Developer Support plans.