Account does not enabled REST API - Server-to-Server OAuth

I’m trying to move from JWT to Server-to-Server OAuth, and despite having set-up everything correctly as far as I can tell, I’m getting a reply that the “Account does not enabled REST API”.

{“code”:200,“message”:“Account does not enabled REST API.”}

We are using .Net C# in our application.

public class ZoomMeeting
{
private const string BaseUrl = “https://api.zoom.us/v2”;
private const string ClientId = “{using-clientid}”;
private const string ClientSecret = “{using-clientsecret}”;

public async Task<string> CreateMeeting()
{
    // Step 1: Get an access token
    var accessToken = await GetAccessToken();

    if (string.IsNullOrEmpty(accessToken))
    {
        // Handle error when unable to retrieve the access token
        return "Failed to retrieve access token";
    }

    // Step 2: Create a meeting
    var httpClient = new HttpClient();
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    var request = new
    {
        topic = "Sample Meeting",
        type = 2, // Scheduled meeting
        start_time = DateTime.UtcNow.AddMinutes(10).ToString("yyyy-MM-ddTHH:mm:ssZ"), // Start time in UTC
        duration = 60, // Duration in minutes
        timezone = "America/Los_Angeles",
        settings = new
        {
            join_before_host = true,
            mute_upon_entry = true,
            auto_recording = "cloud"
        }
    };

    var json = Newtonsoft.Json.JsonConvert.SerializeObject(request);
    var content = new StringContent(json);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

    var createMeetingUrl = "https://api.zoom.us/v2/users/{activeuser-emailid}/meetings";
    var response = await httpClient.PostAsync(createMeetingUrl, content);

    if (response.IsSuccessStatusCode)
    {
        var result = await response.Content.ReadAsStringAsync();
        // Parse the JSON response to get the meeting details
        // You can retrieve the join URL, meeting ID, and other information from the response
        return result;
    }

    // Handle error when unable to create the meeting
    return "Failed to create meeting";
}

private async Task GetAccessToken()
{
var httpClient = new HttpClient();
var request = new
{
grant_type = “client_credentials”,
client_id = ClientId,
client_secret = ClientSecret
};

    var json = Newtonsoft.Json.JsonConvert.SerializeObject(request);
    var content = new StringContent(json);
    content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

    var tokenUrl = "https://zoom.us/oauth/token";
    var response = await httpClient.PostAsync(tokenUrl, content);
   
    if (response.IsSuccessStatusCode)
    {
        var result = await response.Content.ReadAsStringAsync();
        dynamic jsonResult = Newtonsoft.Json.JsonConvert.DeserializeObject(result);
        return jsonResult.access_token;
    }

    return response.StatusCode.ToString();
}

static internal async Task ReadResponseTextForResponseAsync(WebResponse authorizationResponse)
{
string authorizationResponseText;
using (Stream authorizationResponseStream = authorizationResponse.GetResponseStream())
{
UTF8Encoding textEncoderWithoutBOM = new UTF8Encoding(false);
long responseLengthLong = authorizationResponse.ContentLength;
if (0 <= responseLengthLong)
{
int responseRemainder = (int)responseLengthLong;
byte responseBytes = new byte[responseRemainder];
int responseIndex = 0;
int responseBytesRead;
do
{
responseBytesRead = await authorizationResponseStream.ReadAsync(responseBytes, responseIndex, responseRemainder).ConfigureAwait(false);
responseIndex += responseBytesRead;
responseRemainder -= responseBytesRead;
} while (responseBytesRead != 0);
/* UNDONE: observe response charset. /
authorizationResponseText = textEncoderWithoutBOM.GetString(responseBytes);
}
else
{
int responseRemainder = 4096;
byte[] responseBytes = new byte[responseRemainder];
int responseIndex = 0;
int responseBytesRead;
do
{
responseBytesRead = await authorizationResponseStream.ReadAsync(responseBytes, responseIndex, responseRemainder).ConfigureAwait(false);
responseIndex += responseBytesRead;
responseRemainder -= responseBytesRead;
if (responseIndex == responseBytes.Length)
{
Array.Resize(ref responseBytes, responseIndex + 4096);
responseRemainder += 4096;
}
if (responseRemainder < 1)
{
break;
}
} while (responseBytesRead != 0);
Array.Resize(ref responseBytes, responseIndex);
/
UNDONE: observe response charset. */
authorizationResponseText = textEncoderWithoutBOM.GetString(responseBytes);
}
}
return authorizationResponseText;
}

public async Task GetAccessTokenResponseTextAsync()
{
string authorizationResponseText;
HttpWebRequest authorizationRequest = (HttpWebRequest)WebRequest.Create(“https://zoom.us/oauth/token”);
authorizationRequest.Accept = “application/json”;
authorizationRequest.ContentType = “application/x-www-form-urlencoded; charset=utf-8”;
authorizationRequest.Method = “POST”;
string authorizationRequestBody = “client_id=” + HttpUtility.UrlEncode(“{…}”) + “&client_secret=” + HttpUtility.UrlEncode(“{…}”) + “&grant_type=client_credentials&scope=openid”;
UTF8Encoding textEncoderWithoutBOM = new UTF8Encoding(false);
byte authorizationRequestBodyBytes = textEncoderWithoutBOM.GetBytes(authorizationRequestBody);
authorizationRequest.ContentLength = authorizationRequestBodyBytes.Length;
using (Stream authorizationRequestStream = await authorizationRequest.GetRequestStreamAsync().ConfigureAwait(false))
{
await authorizationRequestStream.WriteAsync(authorizationRequestBodyBytes, 0, authorizationRequestBodyBytes.Length).ConfigureAwait(false);
authorizationRequestStream.Close();
WebResponse authorizationResponse;
try
{
authorizationResponse = await authorizationRequest.GetResponseAsync().ConfigureAwait(false);
}
catch (WebException problem)
{
authorizationResponse = problem.Response;
throw;
}

    using (authorizationResponse)
    {
       
        authorizationResponseText = await ReadResponseTextForResponseAsync(authorizationResponse).ConfigureAwait(false);
        authorizationResponse.Close();
    }
}

return authorizationResponseText;

}

public string GetAccessTokenFromAuthorizationResponse(string authorizationResponseText, out int accessTokenLifetimeSeconds)
{
System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
Dictionary<string, object> authorizationResponseObject = serializer.Deserialize<Dictionary<string, object>>(authorizationResponseText);
string accessToken = (string)authorizationResponseObject[“access_token”];
accessTokenLifetimeSeconds = (int)authorizationResponseObject[“expires_in”];
return accessToken;
}

Hi @themindandcompany
Thanks for reaching out to us and welcome to our Developer Forum.
It looks like you generating the access token incorrectly.
When using Server to Server Oauth, please make sure that you are passing the correct grant_type=account_credentials

This is how your request url should look like:

curl -X POST https://zoom.us/oauth/token -d ‘grant_type=account_credentials’ -d ‘account_id={accountID}’ -H ‘Host: zoom.us’ -H ‘Authorization: Basic Base64Encoded(clientId:clientSecret)’

Here is a link to our Docs, please make sure to make the proper changes to your request