Clerk machine traffic: session auth rejects API keys and M2M tokens, use acceptsToken
API keys, M2M tokens, and OAuth access tokens are not sessions. A route that only checks the session rejects them. Declare which token types a handler accepts.
Authenticating machine callers
The trap
Your route checks auth() / getAuth() for a session. A service calling with a Clerk API key or an M2M token has no session, so it gets a 401 even though its credential is valid. Session auth and machine auth are different checks.
The pattern
In Next.js Route Handlers, pass acceptsToken to auth() to declare which machine token types the handler accepts alongside sessions:
const { userId } = await auth({ acceptsToken - 'api_key' })Clerk's docs call this out for machine requests (API keys, OAuth tokens, machine tokens) hitting Route Handlers.
On the backend SDK side, authenticateRequest() accepts the same concept: it requires the publishable key unless acceptsToken is set to api_key or m2m_token. For M2M tokens specifically, the backend SDK exposes a dedicated verify() for M2M token verification.
Checklist
- Decide per route: user sessions only, machine tokens only, or both. Do not leave it ambiguous; ambiguous routes either reject legit automation or accept sessions where only machines should call.
- API keys identify the caller; map the key to permissions server-side rather than trusting the key's existence alone.
- OAuth access tokens from third-party providers are verified with Clerk's OAuth token verification helpers, not the session flow.
- Log which token type authenticated each request. When a partner's integration breaks, "session vs machine" is the first branch in the diagnosis.
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.