Tokens
Authorization flow
1
Redirect the user to the consent page
Open the user’s browser at the Lunacal authorization page:
redirect_uri— required. Must be registered for your client.state— recommended. An opaque random string; it is returned unchanged so you can guard against CSRF.client_id— optional. Your OAuth client ID.
2
The user approves access
The user signs in (if needed) and clicks Allow. Lunacal redirects the browser to your Verify that
redirect_uri:state matches the value you sent.3
Exchange the code for tokens
Within 10 minutes, send the code to The response contains
POST https://app.lunacal.ai/api/mcp/token. The code goes in the Authorization header and your client credentials go in the body:accessToken, expiresAt, refreshToken and refreshTokenExpiresAt. The code is single-use; a missing, invalid, used or expired code or secret returns 400.4
Call the API
Include the access token on every request:
5
Refresh before expiry
When the access token expires (after 1 hour), call The response has the same fields as the token exchange.
POST https://app.lunacal.ai/api/mcp/refresh to get a new token pair:Token rotation
Every call to/api/mcp/refresh rotates both tokens. The refresh token you submit is invalidated immediately.
Security best practices
- Keep your client secret on your server. Never ship it in browser or mobile code.
- Store access and refresh tokens encrypted at rest.
- Always send and verify the
stateparameter. - Refresh tokens proactively using the
expiresAtvalue instead of waiting for a401.