TL;DR: Use the stored refresh token to mint a new access token, retry the meeting create once, and remember to store the rotated refresh token too. Then add a pre-call expiry check so the agent refreshes before the token dies instead of mid-run.

```text
Zoom API 124 "invalid access token"
```

1. Call Zoom's OAuth token endpoint with the stored refresh token to get a fresh access token. Expected: a 200 response with a new access token and expiry.
2. Retry the failed meeting-create with the new token. Expected: the meeting is created successfully.
3. Store the new refresh token as well, since Zoom rotates it on use. Expected: the credential store holds the latest pair.
4. Add a guard: before Zoom calls, the agent checks token expiry and refreshes when less than a few minutes remain, alerting if refresh fails. Expected: no more 124s interrupting runs.

## Use this when
- Zoom API calls return 124 after previously succeeding.
- The agent runs longer than the token lifetime.
- Meeting creation worked an hour ago and now fails.

## Not for this skill when
- The token endpoint itself returns 401 (wrong app credentials, not expiry).
- The error is Zoom 3001 meeting not found (stale meeting ID).
- The error is 429 (rate limiting).

## Variant phrasings
- "Zoom API invalid token 124"
- "Zoom 401 invalid access token"
- "Zoom OAuth token expired"
- "Zoom meeting create unauthorized"

## Why it happens
Zoom user-level OAuth access tokens live about an hour, and recruiting agents that schedule all day outlive them. The agent keeps presenting the stale token because nothing checks expiry before calls.

## Edge cases
- The refresh token itself can expire; then a human must re-authorize the app.
- Server-to-server OAuth apps have different token lifetimes than user OAuth apps.
- Concurrent agent instances racing to refresh can invalidate each other's tokens; serialize the refresh behind a lock.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_R5B7CBpg5C79grh-iQFg-g
