Zoom Docs export endpoint rejects admin scope variant on S2S OAuth apps

Hey all — running into what looks like a scope-matching bug with the new Docs export endpoint that shipped on March 30. Wanted to flag it and see if anyone else has hit this.

What I’m trying to do

Pull the content of my own AI-generated meeting notes (“My notes” in the Zoom Hub sidebar) into a personal knowledge base. The export endpoint looked like exactly the right tool.

The setup

Server-to-Server OAuth app. I added every Docs-related scope I could find in the picker:

docs:read:file:admin
docs:read:list_children:admin
docs:read:import:admin
docs:read:data_table:admin
docs:read:data_table_row:admin
docs:read:list_file_collaborators:admin
docs:read:export:admin
docs:write:export:admin

All of them show up in the access token’s scope field, so the grant is definitely there.

What happens when I call the endpoint

curl -H “Authorization: Bearer $TOKEN”
https://api.zoom.us/v2/docs/files/{fileId}/content

Returns:

HTTP/1.1 401 Unauthorized
{“code”:104,“message”:“Invalid access token, does not contain scopes:[docs:read:export]”}

So the endpoint is rejecting my token because it wants docs:read:export — the non-admin version of the scope. That variant isn’t selectable in the S2S OAuth scope picker; only the :admin version is. Seems like a mismatch between what the endpoint accepts and what S2S apps can actually be granted.

A second thing I noticed while digging

Not sure if it’s related, but while tracking down file IDs to test against, I found that GET /v2/docs/files/{folderId}/children on the “My notes” folder returns {“files”:
} — even though the web UI at Zoom Docs - open page shows nine notes in that folder. The folder itself shows up fine when I list root, and the ID matches.
Individual file IDs pulled from Zoom Docs - open page URLs also return 404 “fileID not found” on the metadata endpoint.

So it seems like the AI-generated notes live somewhere that the Docs API can see them enough to acknowledge the folder, but not enough to list them as children or expose them individually.

Why this matters

The changelog for the export endpoint basically described my exact use case — getting AI Companion meeting content out of Zoom programmatically — so I was pretty excited when I saw it land. Right now though, it’s unreachable from S2S OAuth, which is the only app type that really makes sense for a backend sync job. I’d love for either:

  1. The export endpoint to accept docs:read:export:admin, same way most other admin scopes work, OR
  2. Some guidance on where AI notes live in the Docs API (if they’re supposed to appear in folder children but aren’t) or how to properly access them from a server-side
    integration

For reference, I’ve seen this thread from March mentioning the scope pickers being incomplete, and this one from folks trying to do roughly the same integration. Not sure if those are all manifestations of the same issue or separate bugs.

Happy to run additional repros or share more curl output if it helps.

Thanks!

Hi @Ryan22,

It looks like you’re hitting a mismatch between Account-level and User-level scopes.

I checked the scope picker for a General App (User-managed), and the exact docs:read:export scope you’re looking for is available there. Is there a specific reason you’re wanting to use the Server-to-Server app type?

Could you try creating a General App and adding the docs:read:export scope? Once you’ve done that, you should be able to generate tokens that will be authorized to call the https://api.zoom.us/v2/docs/files/{fileId}/content endpoint.

If you’re still having trouble, there’s always the option of building your own Zoom notetaker to transcribe/summarize your meetings via an API.

@Ryan22

This API works on General Apps’ User Level and Admin Level OAuth. The scopes are available on General Apps.

Server to Server OAuth does not work with this endpoint as it does not have the scope associated with it.

Thanks, Amanda, and Chun! This clears it up completely. I’ll switch to a General App with
User-level OAuth and use the docs:read:export scope. Appreciate you both taking the time to dig into this!