C# sample
Zoom API and SDK reference
Published ASP.NET Core examples for Zoom webhooks, Server-to-Server OAuth, Client Credentials OAuth, OAuth redirects, Meeting SDK signatures, token refresh, and REST API calls.
Live demo
Code samples
Webhook handler
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
public static class webhook
{
public static Task GetWebhook(HttpContext context)
{
return Task.Run(() =>
{
// Handle GET request logic here
context.Response.WriteAsync("GET request received.");
});
}
public static Task PostWebhook(HttpContext context)
{
return Task.Run(async () =>
{
// Get the request content as a string asynchronously
string requestBody = await new StreamReader(context.Request.Body).ReadToEndAsync();
try
{
JObject jsonObject = JObject.Parse(requestBody);
if (jsonObject["event"]?.ToString() != "endpoint.url_validation")
{
await context.Response.WriteAsync("Success.");
return;
}
JObject payload = (JObject)jsonObject["payload"];
string plainToken = payload["plainToken"].ToString();
string secretToken = Environment.GetEnvironmentVariable("OAUTH_SECRET_TOKEN") ?? "";
string encryptedToken = GetHash(plainToken, secretToken);
var response = new
{
plainToken,
encryptedToken
};
context.Response.ContentType = "application/json";
// Write the JSON response
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
}
catch (Exception ex)
{
await context.Response.WriteAsync("Error: " + ex.ToString());
}
});
}
static string GetHash(string text, string key)
{
using (HMACSHA256 sha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(text));
return BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
}
}
Server-to-Server OAuth token
using Newtonsoft.Json;
using System.Text;
using System.Text.Json;
public class s2soauth
{
public static Task S2SOauth(HttpContext context)
{
return Task.Run(async () =>
{
string s2s_oauth_client_id = Environment.GetEnvironmentVariable("S2S_OAUTH_CLIENT_ID");
string s2s_oauth_client_secret = Environment.GetEnvironmentVariable("S2S_OAUTH_CLIENT_SECRET");
string s2s_oauth_account_id = Environment.GetEnvironmentVariable("S2S_OAUTH_ACCOUNT_ID");
// Access the environment variables
var clientId = s2s_oauth_client_id;
var clientSecret = s2s_oauth_client_secret;
var accountId = s2s_oauth_account_id;
var oauthUrl = $"https://zoom.us/oauth/token?grant_type=account_credentials&account_id={accountId}";
try
{
// Create the Basic Authentication header
var authHeader = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
// Initialize HttpClient
using var client = new HttpClient();
// Create request message
var request = new HttpRequestMessage(HttpMethod.Post, oauthUrl);
request.Headers.Add("Authorization", $"Basic {authHeader}");
// Send request and get response
var response = await client.SendAsync(request);
// Check if the request was successful (status code 200)
if (response.IsSuccessStatusCode)
{
// Parse the JSON response to get the access token
var jsonResponse = await response.Content.ReadAsStringAsync();
var accessToken = JsonDocument.Parse(jsonResponse).RootElement.GetProperty("access_token").GetString();
// Set the "Content-Type" header to "application/json"
await context.Response.WriteAsync(JsonConvert.SerializeObject(accessToken));
}
else
{
await context.Response.WriteAsync($"OAuth Request Failed with Status Code: {response.StatusCode}");
}
}
catch (Exception e)
{
await context.Response.WriteAsync($"An error occurred: {e.Message}");
}
});
}
}
Client Credentials OAuth token
using Microsoft.AspNetCore.Http;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
// Program.cs
// app.MapGet("/clientcredential", clientcredential.ClientCredential);
public static class clientcredential
{
public static async Task ClientCredential(HttpContext context)
{
var clientId =
Environment.GetEnvironmentVariable("CLIENT_CREDENTIALS_CLIENT_ID") ??
Environment.GetEnvironmentVariable("OAUTH_CLIENT_ID");
var clientSecret =
Environment.GetEnvironmentVariable("CLIENT_CREDENTIALS_CLIENT_SECRET") ??
Environment.GetEnvironmentVariable("OAUTH_CLIENT_SECRET");
if (string.IsNullOrWhiteSpace(clientId) || string.IsNullOrWhiteSpace(clientSecret))
{
context.Response.StatusCode = 500;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("{\"error\":\"Client credentials OAuth is not configured\"}");
return;
}
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{clientId}:{clientSecret}"));
using var client = new HttpClient();
using var request = new HttpRequestMessage(
HttpMethod.Post,
"https://zoom.us/oauth/token?grant_type=client_credentials"
);
request.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var response = await client.SendAsync(request);
var body = await response.Content.ReadAsStringAsync();
context.Response.StatusCode = (int)response.StatusCode;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(body);
}
}
OAuth redirect exchange
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
public static class redirectforoauth
{
public static Task RedirectForOauth(HttpContext context)
{
return Task.Run(async () =>
{
String AppClientID = Environment.GetEnvironmentVariable("OAUTH_CLIENT_ID"); ;
String AppClientSecret = Environment.GetEnvironmentVariable("OAUTH_CLIENT_SECRET"); ;
String redirectURL = "https://csharp.asdc.cc/redirectforoauth";
var authorizationToken = context.Request.Query["code"].ToString();
try
{
using (HttpClient _httpClient = new HttpClient())
{
var url = "https://zoom.us/oauth/token";
using var client = new HttpClient();
// Encode the client ID and client secret
var credentials = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{AppClientID}:{AppClientSecret}"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", credentials);
var content = new FormUrlEncodedContent(new Dictionary
{
{ "grant_type", "authorization_code" },
{ "redirect_uri", redirectURL },
{ "code", authorizationToken }
});
var response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
await context.Response.WriteAsync(JsonConvert.SerializeObject(responseContent));
}
else
{
// Handle error response
await context.Response.WriteAsync(JsonConvert.SerializeObject(response.StatusCode));
}
}
}
catch (HttpRequestException ex)
{
// Handle HTTP request exceptions
Console.WriteLine($"HTTP Request Exception: {ex.Message}");
//throw new Exception($"HTTP Request Exception: {ex.Message}");
}
catch (System.Text.Json.JsonException ex)
{
// Handle JSON parsing exceptions
Console.WriteLine($"JSON Parsing Exception: {ex.Message}");
throw new Exception($"JSON Parsing Exception: {ex.Message}");
}
catch (Exception ex)
{
// Handle other exceptions
Console.WriteLine($"Exception occurred: {ex.Message}");
throw new Exception($"Exception occurred: {ex.Message}");
}
});
}
internal static RequestDelegate RedirectForOauth(string? oAUTH_CLIENT_ID, string? oAUTH_CLIENT_SECRET)
{
throw new NotImplementedException();
}
}
Meeting SDK signature sample
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Threading.Tasks;
public static class meetingsdk
{
public static async Task MeetingSDK(HttpContext context)
{
var response = new
{
message = "Live Meeting SDK signature generation is disabled on this public demo.",
liveSignatureGenerationDisabled = true,
requestShape = new
{
method = "POST",
body = new
{
meetingNumber = "{MEETING_NUMBER}",
role = "0 for attendee, 1 for host"
}
},
jwtPayloadShape = new
{
appKey = "{APP_KEY}",
mn = "{MEETING_NUMBER}",
role = "0 or 1",
iat = "{UNIX_TIMESTAMP}",
exp = "{UNIX_TIMESTAMP}",
tokenExp = "{UNIX_TIMESTAMP}"
},
expectedResponseFields = new[]
{
"signature",
"appKey"
}
};
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
}
}
OAuth refresh token
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public static class oauthrefreshtoken
{
public static Task OauthRefreshToken(HttpContext context)
{
return Task.Run(async () =>
{
var oauthClientId = Environment.GetEnvironmentVariable("OAUTH_CLIENT_ID");
var oauthClientSecret = Environment.GetEnvironmentVariable("OAUTH_CLIENT_SECRET");
var refreshToken = context.Request.Query["code"].ToString();
var url = "https://zoom.us/oauth/token";
var credentials = $"{oauthClientId}:{oauthClientSecret}";
var credentialsEncoded = Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials));
var data = new Dictionary
{
{ "grant_type", "refresh_token" },
{ "refresh_token", refreshToken }
};
var content = new FormUrlEncodedContent(data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentialsEncoded);
var response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode)
{
var jsonResponse = await response.Content.ReadAsStringAsync();
var accessToken = JsonDocument.Parse(jsonResponse).RootElement.GetProperty("access_token").GetString();
// Set the "Content-Type" header to "application/json"
await context.Response.WriteAsync(JsonConvert.SerializeObject(accessToken));
}
else
{
await context.Response.WriteAsync($" Request Failed with Status Code: {response.StatusCode}");
}
});
}
}
REST API call
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class callapi
{
public static Task CallAPI(HttpContext context)
{
return Task.Run(async () =>
{
// Fetch access_token from query string
var access_token = context.Request.Query["access_token"];
if (string.IsNullOrWhiteSpace(access_token))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync("Add ?access_token=your_token to call the API");
return;
}
// Meeting data
var meeting_data = new
{
topic = "hello world",
type = 2,
start_time = DateTime.UtcNow.AddHours(1).ToString("yyyy-MM-ddTHH:mm:ssZ"),
duration = 120,
password = "12345678",
agenda = "40 mins limit demonstration",
pre_schedule = false,
timezone = "Asia/Singapore",
default_password = false
};
// Zoom API endpoint
var api_url = "https://api.zoom.us/v2/users/me/meetings";
// Send POST request to create meeting
using var client = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Post, api_url);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", access_token);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
request.Content = new StringContent(JsonSerializer.Serialize(meeting_data), Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
// Return response
await context.Response.WriteAsync("Meeting Details: " + await response.Content.ReadAsStringAsync());
});
}
}
Environment variables
S2S_OAUTH_CLIENT_ID='xxxxxxxxxx'
S2S_OAUTH_CLIENT_SECRET='xxxxxxxxxx'
S2S_OAUTH_ACCOUNT_ID='xxxxxxxxxx'
OAUTH_SECRET_TOKEN='xxxxxxxxxx'
OAUTH_CLIENT_ID='xxxxxxxxxx'
OAUTH_CLIENT_SECRET='xxxxxxxxxx'
CLIENT_CREDENTIALS_CLIENT_ID='xxxxxxxxxx'
CLIENT_CREDENTIALS_CLIENT_SECRET='xxxxxxxxxx'
MSDK_CLIENT_SECRET='xxxxxxxxxx'
MSDK_CLIENT_ID='xxxxxxxxxx'