Can we use an API secret without needing to request OAuth tokens?

I am building a little server-to-server tool that needs to make API calls to check the meetings in an account.

From what I can see in the docs, I need to make a Server-to-Server OAuth app and then I can:

  1. Make an API call with my id:secret with grant_type=account_credentials which gives me an access token
  2. Then I can make API calls with Bearer token

The access token is only valid for an hour. So in my case, every time I want to make the API call, I have to first make the extra call to get the OAuth token. This means an extra call to the API every time I want to query something.

Is there a way to call the meetings API directly with an API secret of some kind? I am only trying to call the API from a server. Do I have to go through the extra step of requesting an OAuth access token all the time?

If not, please help me understand: If I can use a secret to get an access token anytime I want, why can’t I just use that secret to access the API?

Hi Adam, welcome!

You’re on the right track - Zoom has deprecated JWT tokens, so the Server-to-Server OAuth flow is now the only supported way for backend integrations.

You’re correct that you need to use your client_id and client_secret to get an access token with grant_type=account_credentials. However, you don’t need to request a new token on every API call.

Here’s how you can improve your implementation:

  • Cache the token in memory (e.g., in process.zoomauth or a similar object).
  • Only request a new one if no token exists or if the previous one has expired or hit a 429 or 401.
  • Example logic in Node.js:
if (!process.zoomauth?.access_token) {
  process.zoomauth = await getZoomToken();
}

try {
  await callZoomAPI(process.zoomauth.access_token);
} catch (err) {
  if (err.response?.status === 429 || err.response?.status === 401) {
    process.zoomauth = await getZoomToken();
    await callZoomAPI(process.zoomauth.access_token);
  }
}

This approach avoids hitting the token endpoint every time, while still ensuring you have a valid token when needed.

Let me know if you need help with a token handler or wrapper!

Best,
Naeem Ahmed

Thanks for the detailed reply. I am building a microservice function being run on CloudFlare Workers, so it doesn’t make as much sense to store the access token in memory. There are options for caching/persistence but it is a bit of a pain.

I’m just wondering what the security rationale behind this extra step is. If I can use the client_secret to get a token whenever I want, and my requests are encoded, why shouldn’t I be able to access the API with this client_secret ? I don’t see how the extra step (requesting the access token) is helpful or necessary.

hi @AdamDev ,

The method is that you start with your id and secret
you use oauth to get your secure token and your refresh token
You use the secure token when using api calls
When that secure token expires, you use the refresh token to get a new one.

So, to use most API calls, you must have the token.
However, there are a set of inmeeting apis, and they dont need the token.

Hope that covers it all
all the best

John

1 Like

Having a long-lived secret be separate from a short-lived access token lets you isolate the secret into a separate component that is closely guarded / designed. This component can retrieve a fresh access token and distribute it to less trusted components (say, that might be maintained by another / outsourced development team). If the access token is leaked, it will only remain valid for a short period of time.

1 Like