# 401 unauthorized in powershell API call

**URL:** <https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614>\
**Category:** API and Webhooks\
**Created:** [August 11, 2021, 1:30pm UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614 "2021-08-11T13:30:58Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pew05](https://avatars.discourse-cdn.com/v4/letter/p/97f17d/32.png) [@Pew05](https://devforum.zoom.us/u/Pew05)\
**Post date:** [August 11, 2021, 1:30pm UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/1 "2021-08-11T13:30:59Z")

</div>

**Description**  
I’m trying to simply get a channel ID. I found the powershell module PSZoom, which works, but will not return the info I need AFAIK. I took some code from the individual functions in the modules to build the code below. It runs, but returns a 401 unauthorized error

**Error**  
401 unauthorized when trying to get channel lists for my user

**Which App?**  
Custom app, JWT

**How To Reproduce (If applicable)**  
Run script below

**Additional context**  
All code is from the PSZoom module

Note that APIkey and APIsecret are saved to variables, removed prior to posting. Bolded text near the end contains my user id obtained from get-zoomuser

Import-Module pszoom

function New-Jwt  
{  
param (  
[Parameter(Mandatory = $True)]  
[ValidateSet(‘HS256’, ‘HS384’, ‘HS512’)]  
[string]$Algorithm,  
$Type = $null,  
[Parameter(Mandatory = $True)]  
[string]$Issuer,  
[int]$ValidforSeconds = $null,  
[Parameter(Mandatory = $True)]  
[string]$SecretKey  
)

```
Write-Verbose 'Generating JWT'
$Exp = [int][double]::parse((Get-Date -Date $((Get-Date).addseconds($ValidforSeconds).ToUniversalTime()) -UFormat %s)) # Grab Unix Epoch Timestamp and add desired expiration

$Header = @{
	alg = $Algorithm
	typ = $Type
}

$Payload = @{
	iss = $Issuer
	exp = $Exp
}

$Headerjson = $Header | ConvertTo-Json -Compress
$Payloadjson = $Payload | ConvertTo-Json -Compress

$Headerjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Headerjson)).Split('=')[0].Replace('+', '-').Replace('/', '_')
$Payloadjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Payloadjson)).Split('=')[0].Replace('+', '-').Replace('/', '_')

$ToBeSigned = $Headerjsonbase64 + "." + $Payloadjsonbase64

$SigningAlgorithm = switch ($Algorithm)
{
	"HS256" { New-Object System.Security.Cryptography.HMACSHA256 }
	"HS384" { New-Object System.Security.Cryptography.HMACSHA384 }
	"HS512" { New-Object System.Security.Cryptography.HMACSHA512 }
}

$SigningAlgorithm.Key = [System.Text.Encoding]::UTF8.GetBytes($SecretKey)
$Signature = [Convert]::ToBase64String($SigningAlgorithm.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($ToBeSigned))).Split('=')[0].Replace('+', '-').Replace('/', '_')

$Token = "$Headerjsonbase64.$Payloadjsonbase64.$Signature"

Write-Output $Token

```

}

function Get-ZoomApiCredentials  
{  
[CmdletBinding()]  
Param (  
[string]$ZoomApiKey,  
[string]$ZoomApiSecret  
)

```
try
{
	Write-Verbose -Message 'Retrieving Zoom API Credentials.'
	
	if (-not $Global:ZoomApiKey)
	{
		if (-not [string]::IsNullOrWhiteSpace($ZoomApiKey))
		{
			$Global:ZoomApiKey = $ZoomApiKey
		}
		else
		{
			$Global:ZoomApiKey = if ($PSPrivateMetadata.JobId)
			{
				Get-AutomationVariable -Name ZoomApiKey
			}
			else
			{
				Read-Host 'Enter Zoom Api key (push ctrl + c to exit)'
			}
		}
	}
	
	if (-not $Global:ZoomApiSecret)
	{
		if (-not [string]::IsNullOrWhiteSpace($ZoomApiSecret))
		{
			$Global:ZoomApiSecret = $ZoomApiSecret
		}
		else
		{
			$Global:ZoomApiSecret = if ($PSPrivateMetadata.JobId)
			{
				Get-AutomationVariable -Name ZoomApiSecret
			}
			else
			{
				Read-Host 'Enter Zoom Api Secret (push ctrl + c to exit)'
			}
		}
	}
	
	@{
		'ApiKey' = $Global:ZoomApiKey
		'ApiSecret' = $Global:ZoomApiSecret
	}
	
	Write-Verbose 'Retrieved API Credentials.'
}
catch
{
	Write-Error "Problem getting Zoom Api Authorization variables:`n$_"
}

```

}

function New-ZoomHeaders  
{  
param (  
[string]$ApiKey,  
[string]$ApiSecret  
)  
$Credentials = Get-ZoomApiCredentials -ZoomApiKey $ApiKey -ZoomApiSecret $ApiSecret  
$Token = New-Jwt -Algorithm ‘HS256’ -type ‘JWT’ -Issuer $Credentials.ApiKey -SecretKey $Credentials.ApiSecret -ValidforSeconds 30

```
Write 'Generating Headers'
$Headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$Headers.Add('content-type', 'application/json')
$Headers.Add('authorization', 'bearer ' + $Token)

Write-Output $Headers

```

}

$Headers = New-ZoomHeaders -ApiKey $ApiKey -ApiSecret $ApiSecret  
$Request = [System.UriBuilder]“[https://api.zoom.us/v2/chat/users/](https://api.zoom.us/v2/chat/users/) **MY USER ID** /channels”

write $Headers

$response = Invoke-RestMethod -Uri $request.Uri -Headers $Headers -Method POST

$response

---

<div class="post-metadata">

**Author:** ![gianni.zoom](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/gianni.zoom/32/32523_2.png) [@gianni.zoom](https://devforum.zoom.us/u/gianni.zoom)\
**Post date:** [August 12, 2021, 9:49pm UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/2 "2021-08-12T21:49:17Z")

</div>

Hi @Pew05 ,

Welcome to the Dev Forum! I am unfamiliar with the powershell module PSZoom as it it not a Zoom created product, but can you please clarify what information you’re looking to return via channel ID that it does not show?

Thanks,  
Gianni

---

<div class="post-metadata">

**Author:** ![maci01](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maci01/32/2129_2.png) [@maci01](https://devforum.zoom.us/u/maci01)\
**Post date:** [August 16, 2021, 3:11am UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/3 "2021-08-16T03:11:12Z")

</div>

Hi, I made the module and can help. Are you trying to use this API call: [https://marketplace.zoom.us/docs/api-reference/zoom-api/chat-channels/getchannels](https://marketplace.zoom.us/docs/api-reference/zoom-api/chat-channels/getchannels) ?

I think maybe you’re using POST when you should be using GET for the method parameter. This should work (I don’t use chat and can’t test really):

```auto
import-module pszoom
$userID = 'put_user_id_here'
$Request = [System.UriBuilder]"https://api.zoom.us/v2/chat/users/$userID/channels"
Invoke-ZoomRestMethod -Uri $request.Uri -ApiKey $your_api_key -ApiSecret $your_api_secret -Method GET

```

Let me know how it turns out.

---

<div class="post-metadata">

**Author:** ![Pew05](https://avatars.discourse-cdn.com/v4/letter/p/97f17d/32.png) [@Pew05](https://devforum.zoom.us/u/Pew05)\
**Post date:** [August 16, 2021, 12:09pm UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/4 "2021-08-16T12:09:23Z")

</div>

Hello, thank you for your reply. That is how I started, but I can’t get it to connect. When I run what you provided above with my api key, secret and userID, I get this:

ERROR: Invoke-ZoomRestMethod : **The remote server returned an error: (401) Unauthorized. This API only supports oAuth2 for authorization.**  
get-channelid2.ps1 (23, 1): ERROR: At Line: 23 char: 1  
ERROR: + Invoke-ZoomRestMethod -Uri $request.Uri -ApiKey $apikey -ApiSecret $a …  
ERROR: + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  
ERROR: + CategoryInfo : AuthenticationError: ([https://api.zoo](https://api.zoo)…XGcU\_A/channels:) [Write-Error], This API only s… authorization.  
ERROR: + FullyQualifiedErrorId : 401,Invoke-ZoomRestMethod

---

<div class="post-metadata">

**Author:** ![maci01](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maci01/32/2129_2.png) [@maci01](https://devforum.zoom.us/u/maci01)\
**Post date:** [August 17, 2021, 8:18pm UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/5 "2021-08-17T20:18:27Z")

</div>

> **This API only supports oAuth2 for authorization**

There’s your issue. PSZoom uses JWT. I’m not sure how to implement oauth2 in PowerShell.

---

<div class="post-metadata">

**Author:** ![MaxM](https://sea2.discourse-cdn.com/flex016/user_avatar/devforum.zoom.us/maxm/32/42303_2.png) [@MaxM](https://devforum.zoom.us/u/MaxM)\
**Post date:** [August 18, 2021, 2:07am UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/6 "2021-08-18T02:07:41Z")

</div>

Hey @maci01,

Thanks for sharing your insight here! @Pew05 I don’t have any experience with OAuth2 and Powershell either. Let me know if this 3rd party guide helps:

> **[Use PowerShell to make Rest API calls using JSON & OAuth](https://marckean.com/2015/09/21/use-powershell-to-make-rest-api-calls-using-json-oauth/)**
>
> If you come from an IT Pro background like me, I have probably scared you off already by mentioning terms like Rest API, RegEx, JSON & OAuth. But don’t worry, I am going to walk you though some…

Thanks,  
Max

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex016/uploads/zoomdeveloper/original/3X/6/1/614bdd549b610bbaa46ff934617683a02bdaa03c.png) [@system](https://devforum.zoom.us/u/system)\
**Post date:** [September 17, 2021, 12:08pm UTC](https://devforum.zoom.us/t/401-unauthorized-in-powershell-api-call/55614/7 "2021-09-17T12:08:39Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
