Documentation
OAuth ServerReference

Reference

Endpoints, scopes, protocol errors and the settings that control the OAuth Server.

Everything the authorization server exposes, in one place. For SDK method signatures see auth.oauth; for nulvless error codes see Error codes.

All paths are relative to your issuer.

Endpoints

MethodPathAuthWhat it does
GET/.well-known/openid-configurationpublicDiscovery document
GET/.well-known/jwks.jsonpublicPublic signing keys
GET/oauth/authorizepublicStarts the flow, redirects to your consent screen
GET/oauth/authorizations/:idsessionWhat a pending authorization is asking for
POST/oauth/authorizations/:id/consentsessionRecords approve or deny
POST/oauth/tokenclientExchanges a code, or refreshes
GET/oauth/userinfobearerClaims for the granted scopes
POST/oauth/registerpublicDynamic client registration, when enabled

"Public" means no API key. The two authorization endpoints act on behalf of the signed-in user, which is what ties consent to a person.

GET /oauth/authorize

ParameterRequiredNotes
client_idyes
redirect_uriyesExact match against a registered URI
response_typeyescode
code_challengeyesBase64url SHA-256 of the verifier
code_challenge_methodyesS256
scopenoSpace separated; defaults to email
statenoReturned untouched
noncenoEchoed into the ID token
resourcenoThe API the token is for

Answers 403 when the OAuth Server is disabled for the environment.

POST /oauth/token

Parameterauthorization_coderefresh_token
grant_typerequiredrequired
coderequired—
redirect_urirequired—
code_verifierrequired—
refresh_token—required
client_idrequiredrequired
client_secretconfidential clientsconfidential clients
{
  "access_token": "…",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "…",
  "id_token": "…"
}

id_token is present only when openid was granted.

Scopes

ScopeClaims
openidIssues an ID token
emailemail, email_verified
profilename, picture
phonephone_number, phone_number_verified

Protocol errors

These are OAuth 2.1 error strings, distinct from nulvless error codes. Where they surface depends on whether the redirect URI has been validated — see the flow.

ErrorMeaning
invalid_requestMissing or malformed parameter
invalid_clientUnknown client, or bad secret
invalid_grantCode expired, already used, or code_verifier does not match
unauthorized_clientClient may not use this grant type
unsupported_response_typeAnything other than code
invalid_scopeScope not in the supported set
access_deniedThe user pressed Deny
server_errorFault on our side

The two worth handling specifically are invalid_grant — usually a replayed or expired code, and always a restart of the flow — and access_denied, which is a user decision and should be a calm message rather than an error page.

Settings

Found in the Console under OAuth Server, per environment.

Enabledboolean, default offOptional

While off, /oauth/authorize answers 403.

Consent screen URLdefaults to Site URLOptional

Base URL of your consent screen, for when it is not hosted on your Site URL.

Authorization pathdefault /oauth/consentOptional

Path of your consent screen, appended to the URL above.

Allow dynamic clientsboolean, default offOptional

Enables POST /oauth/register. See the trade-off.

Site URL lives under the project's URL settings, not here — it is the same value used for confirmation links.

Caching

ResponseHeader
Discovery documentCache-Control: public, max-age=3600
JWKSCache-Control: public, max-age=600
Everything elseCache-Control: no-store

no-store on token responses is required by RFC 6749 §5.1 and OpenID Connect Core §3.1.3.3. The two public documents opt out deliberately, because every client fetches them constantly and they contain no secrets.

On this page