Phone Recording Error "Invalid access token, does not contain scopes:[]."

API Endpoint(s) and/or Zoom API Event(s)
https://zoom.us/v2/phone/recording/download/{download_url_key} given as the download_url when getting recordings from https://zoom.us/v2/phone/recordings

Description
The scopes that are missing are blank in the error message.

Error
{
“code”: 104,
“message”: “Invalid access token, does not contain scopes:.”
}

How To Reproduce
Steps to reproduce the behavior:

  1. Request https://zoom.us/v2/phone/recording/download/{download_url_key} with bearer token.
  2. Verify Bearer Token is correct for other endpoints
  3. Get 401 listed above
1 Like

Hi @stephen1 , were there any scopes listed in the response?

Is this the first time you are seeing this behavior?

I see this may be a bug from another user experiencing the same behavior. Can you please share the zm-tracking-id that you can see in the response headers from the request?

Here is one ifrom one of my requests that is seeing the same error WEB_8a6df7bd76325898cc47d880a4be8a46

no the scopes are empty in the response []

No scopes whatever. That is the issue.

Here is the tracking-id: WEB_9b6f25301ede6b785cd214287c0eff35

@kdawgwilk-elephant @stephen1

There are two issues I’m observing:

  1. Some people have the correct scopes enabled, but are getting this result when they’re calling the endpoint. See example below:
    Unable to Download Zoom Phone Call Recording - Missing Blank [] Scopes

  2. Some people do not see scopes they’d need to enable on the app at all, but are still trying to access certain endpoint with a generated access token.

Which applies to you?

I believe we are seeing both issues actually

Hi @kdawgwilk-elephant ,

Can you please provide the request/responses and tracking ids for scenario 1?

Request URL: https://zoom.us/v2/phone/recording/download/Sgzf8Z7SQ3y3HIh4yFlOdA

Response Headers:

[
  {
    "key": "Date",
    "value": "Thu, 11 Apr 2024 16:34:49 GMT",
    "description": "A general header containing the date and time the message was sent.",
    "info": "A general header containing the date and time the message was sent."
  },
  {
    "key": "Content-Type",
    "value": "application/json",
    "description": "Indicates the resource's media type.",
    "info": "Indicates the resource's media type."
  },
  {
    "key": "Content-Length",
    "value": "74",
    "description": "An entity header indicating the size of the entity-body, in bytes.",
    "info": "An entity header indicating the size of the entity-body, in bytes."
  },
  {
    "key": "Connection",
    "value": "keep-alive",
    "description": "A general header specifying whether the current network connection will stay open once the current transaction finishes.",
    "info": "A general header specifying whether the current network connection will stay open once the current transaction finishes."
  },
  {
    "key": "x-zm-trackingid",
    "value": "WEB_3b2f343f34f1e2ca7649aa8714e2e5d7",
    "description": "Custom header",
    "info": "Custom header"
  },
  {
    "key": "x-zm-region",
    "value": "VA",
    "description": "Custom header",
    "info": "Custom header"
  },
  {
    "key": "vary",
    "value": "Origin",
    "description": "Determines how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one.",
    "info": "Determines how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one."
  },
  {
    "key": "vary",
    "value": "Access-Control-Request-Method",
    "description": "Determines how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one.",
    "info": "Determines how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one."
  },
  {
    "key": "vary",
    "value": "Access-Control-Request-Headers",
    "description": "Determines how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one.",
    "info": "Determines how to match future request headers to decide whether the cached response can be used rather than requesting a fresh one."
  },
  {
    "key": "x-frame-options",
    "value": "deny",
    "description": "Used to avoid clickjacking attacks by making sure their content is not embedded into other sites.",
    "info": "Used to avoid clickjacking attacks by making sure their content is not embedded into other sites."
  },
  {
    "key": "strict-transport-security",
    "value": "max-age=31536000; includeSubDomains",
    "description": "Lets websites tell a browser that they should only be accessed via HTTPS.",
    "info": "Lets websites tell a browser that they should only be accessed via HTTPS."
  },
  {
    "key": "CF-Cache-Status",
    "value": "DYNAMIC",
    "description": "Custom header",
    "info": "Custom header"
  },
  {
    "key": "Report-To",
    "value": "{\"endpoints\":[{\"url\":\"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=KYkcVyt6sg3oFYScyelRfzq3EX3pLzpl1KsNLdcR9xzwmiNREaTGUJZpRsyqGcQ7pQnrtIwhwG5vjIgXAP5n5o7prsRD3VH1KtSWk3MZsPsXwas8AKGdLLs%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}",
    "description": "Custom header",
    "info": "Custom header"
  },
  {
    "key": "NEL",
    "value": "{\"success_fraction\":0.01,\"report_to\":\"cf-nel\",\"max_age\":604800}",
    "description": "Custom header",
    "info": "Custom header"
  },
  {
    "key": "Server",
    "value": "cloudflare",
    "description": "Contains information about how the server handles requests.",
    "info": "Contains information about how the server handles requests."
  },
  {
    "key": "CF-RAY",
    "value": "872c62e01c221f44-DEN",
    "description": "Custom header",
    "info": "Custom header"
  },
  {
    "key": "alt-svc",
    "value": "h3=\":443\"; ma=86400",
    "description": "Custom header",
    "info": "Custom header"
  }
]

Response Body:

{"code":104,"message":"Invalid access token, does not contain scopes:[]."}

@kdawgwilk-elephant @stephen1 ,

The relevant team is working on a fix for the next API release (ZSEE-125372). Waiting for more details confirming all endpoints that will be resolved.

Hello, Zoom team.
I have a question related to this matter. I was able to download Zoom Phone recording using API endpoint and access token generated with Server-To-Server OAuth flow (using Server-To-Server App type). However, I wonder if it is possible to acquire recordings from other Zoom accounts (I’m not sure if Server-To-Server OAuth App can be authorized by other accounts’ admins to enable retrieving theirs recordings) ? If so, would Server-To-Server token be valid for such retrieval ?

Devs still working on this (ZOOM-709449).

Hi @developmentjatheon ,

No Server-to-Server OAuth is an internal app type and cannot access external data. You have to use standard OAuth app type.