How it works
1
Send the user to the authorize endpoint
Your app redirects the browser to
/oauth/authorize with your client_id, a
redirect_uri, the scope, a state, and a PKCE code_challenge.2
The user approves
We show the consent screen with the scopes you requested. The user approves or denies.
3
We redirect back with a code
On approval we redirect to your
redirect_uri with a one time code and your state.
On denial it redirects with error=access_denied.4
Exchange the code for tokens
Your server calls the token endpoint with the
code and the PKCE code_verifier and
receives an access token and a refresh token.Generate PKCE values
PKCE is required. Create a randomcode_verifier, then derive the code_challenge as the
base64url encoded SHA256 of the verifier.
pkce.ts
Step 1: authorize request
Redirect the user to the authorize endpoint.string
required
Must be
code.string
required
Your application
client_id.string
required
Must exactly match one of the redirect URIs registered on the application.
string
required
The base64url SHA256 of your
code_verifier.string
required
Must be
S256.string
An opaque value your app generates. We return it unchanged so you can defend against cross
site request forgery.
Step 2: the redirect back
After the user approves, we redirect to yourredirect_uri.
Step 3: exchange the code
Your server exchanges thecode at the token endpoint. Send your client_secret and the
matching code_verifier.
Step 4: call the API
Send the access token as a bearer token. Read the user who approved access fromGET /api/v1/user.
Refresh the access token
Access tokens last one hour. Use the refresh token to get a new one. Refresh tokens rotate, so replace the stored refresh token with the one you receive back.Effective scopes
The access token is limited to the scopes the user approved, intersected with the scopes the application currently holds. If you later remove a scope from the application, existing tokens lose that scope on their next request.Errors
redirect error
The user declined on the consent screen.
token error
The code was already used, expired, or the
code_verifier did not match the
code_challenge.token error
The
client_id or client_secret is wrong, or the app is disabled.api error
The token is valid but does not carry the scope the endpoint requires.