openapi: 3.0.3
info:
title: Clerk Backend Account Portal OAuth2 Identity Provider API
x-logo:
url: https://clerk.com/_next/image?url=%2Fimages%2Fclerk-logo.svg&w=96&q=75
altText: Clerk docs
href: https://clerk.com/docs
contact:
email: support@clerk.com
name: Clerk Platform Team
url: https://clerk.com/support
description: 'The Clerk REST Backend API, meant to be accessed by backend servers.
### Versions
When the API changes in a way that isn''t compatible with older versions, a new version is released.
Each version is identified by its release date, e.g. `2025-04-10`. For more information, please see [Clerk API Versions](https://clerk.com/docs/versioning/available-versions).
Please see https://clerk.com/docs for more information.'
version: '2025-11-10'
termsOfService: https://clerk.com/terms
license:
name: MIT
url: https://github.com/clerk/openapi-specs/blob/main/LICENSE
servers:
- url: https://api.clerk.com/v1
security:
- bearerAuth: []
tags:
- name: OAuth2 Identity Provider
description: Requests for the OAuth2 authorization flow.
paths:
/oauth/authorize:
get:
summary: Request OAuth2 Authorization
description: Request OAuth2 authorization. If successful, receive authorization grant via redirect.
operationId: requestOAuthAuthorize
security: []
tags:
- OAuth2 Identity Provider
parameters:
- name: response_type
in: query
required: true
description: The authorization flow type. Must be `code` for authorization code flow.
schema:
type: string
enum:
- code
- name: client_id
in: query
required: true
description: The OAuth2 client ID of the OAuth application.
schema:
type: string
- name: redirect_uri
in: query
required: false
description: The URI to redirect to after authorization. Must be registered for the OAuth application.
schema:
type: string
format: uri
- name: scope
in: query
required: false
style: spaceDelimited
explode: false
description: Space-separated list of scopes being requested. Available scopes are `email`, `profile`, `openid`, `public_metadata`, and `private_metadata`. Defaults to `profile email` if not provided.
schema:
type: array
items:
type: string
enum:
- email
- profile
- openid
- offline_access
- public_metadata
- private_metadata
- name: state
in: query
required: false
description: An opaque value used to maintain state between the request and callback (minimum 8 characters). Required to prevent CSRF attacks unless PKCE parameters (`code_challenge` and `code_challenge_method`) are provided.
schema:
type: string
minLength: 8
- name: prompt
in: query
required: false
style: spaceDelimited
explode: false
description: Space-separated list of prompts. Supported values are `none` (no user interaction), `login` (force re-authentication), and `consent` (force consent screen).
schema:
type: array
items:
type: string
enum:
- none
- login
- consent
- name: code_challenge
in: query
required: false
description: The code challenge for PKCE (Proof Key for Code Exchange). Required for public clients.
schema:
type: string
- name: code_challenge_method
in: query
required: false
description: The method used to generate the code challenge. Must be `S256`.
schema:
type: string
enum:
- S256
- name: response_mode
in: query
required: false
description: The method used to return authorization response parameters. Supported values are `query` (parameters in URL query string) and `form_post` (parameters in POST body).
schema:
type: string
enum:
- query
- form_post
- name: nonce
in: query
required: false
description: String value used to associate a client session with an ID Token and to mitigate replay attacks. Used in OpenID Connect flows.
schema:
type: string
responses:
'200':
description: Success for 'form_post' response mode
'302':
description: Redirect, no body.
'303':
description: Redirect, no body.
'400':
description: Bad request error, for example a request parameter is invalid.
'401':
description: Unauthorized error, for example the provided client is invalid.
'403':
description: Forbidden error, for example you are trying to use a satellite domain
post:
summary: Request OAuth2 Authorization
description: Request OAuth2 authorization. If successful, receive authorization grant via redirect.
operationId: requestOAuthAuthorizePOST
security: []
tags:
- OAuth2 Identity Provider
requestBody:
required: false
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
response_type:
type: string
description: The authorization flow type. Must be `code` for authorization code flow.
enum:
- code
client_id:
type: string
description: The OAuth2 client ID of the OAuth application.
redirect_uri:
type: string
format: uri
nullable: true
description: The URI to redirect to after authorization. Must be registered for the OAuth application.
scope:
type: string
nullable: true
description: Space-separated list of scopes being requested. Available scopes are `email`, `profile`, `openid`, `public_metadata`, and `private_metadata`. Defaults to `profile email` if not provided. Multiple values should be space-delimited (e.g., "email profile openid").
state:
type: string
nullable: true
description: An opaque value used to maintain state between the request and callback (minimum 8 characters). Required to prevent CSRF attacks unless PKCE parameters (`code_challenge` and `code_challenge_method`) are provided.
minLength: 8
prompt:
type: string
nullable: true
description: Space-separated list of prompts. Supported values are `none` (no user interaction), `login` (force re-authentication), and `consent` (force consent screen). Multiple values should be space-delimited (e.g., "login consent").
code_challenge:
type: string
nullable: true
description: The code challenge for PKCE (Proof Key for Code Exchange). Required for public clients.
code_challenge_method:
type: string
nullable: true
description: The method used to generate the code challenge. Must be `S256`.
enum:
- S256
response_mode:
type: string
nullable: true
description: The method used to return authorization response parameters. Supported values are `query` (parameters in URL query string) and `form_post` (parameters in POST body).
enum:
- query
- form_post
nonce:
type: string
nullable: true
description: String value used to associate a client session with an ID Token and to mitigate replay attacks. Used in OpenID Connect flows.
required:
- response_type
- client_id
responses:
'200':
description: Success for 'form_post' response mode
'302':
description: Redirect, no body.
'303':
description: Redirect, no body.
'400':
description: Bad request error, for example a request parameter is invalid.
'401':
description: Unauthorized error, for example the provided client is invalid.
'403':
description: Forbidden error, for example you are trying to use a satellite domain
/oauth/register:
post:
summary: Register OAuth 2.0 Client
description: "Registers a new OAuth 2.0 client with the authorization server according to RFC 7591\n(OAuth 2.0 Dynamic Client Registration Protocol).\n\nThis endpoint allows clients to dynamically register by submitting client metadata.\nUpon successful registration, the authorization server assigns a unique client identifier\nand optionally a client secret (for confidential clients).\n\n**Authentication:** This endpoint does not require authentication as it is used for\ninitial client registration. However, the endpoint is disabled by default and must\nbe enabled in the Instance settings.\n\n**Client Types:**\n- **Confidential clients** receive both a `client_id` and `client_secret`\n- **Public clients** (using `token_endpoint_auth_method: none`) receive only a `client_id`\n\n**Key Points:**\n- All dynamically registered clients must use the consent screen (cannot be disabled)\n- PKCE is not required for dynamically registered clients\n- The `redirect_uris` field is required and must contain at least one valid redirect URI\n- If `client_name` is not provided, the `client_id` will be used as the display name\n- If `scope` is not provided, default scopes will be assigned\n- The `token_endpoint_auth_method` values `client_secret_basic` and `client_secret_post` are\n treated equivalently in the current implementation; both methods can be used at the\n token endpoint\n\nSee [RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591) for complete specification details."
operationId: registerOAuthClient
security: []
tags:
- OAuth2 Identity Provider
requestBody:
description: 'Client metadata as defined in RFC 7591 Section 2. The client metadata includes
information about the client such as its name, redirect URIs, and authentication method.'
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OAuth.DynamicClientRegistrationRequest'
examples:
confidentialClient:
summary: Confidential Client Registration
description: Register a confidential client that will authenticate with client_secret_basic
value:
client_name: My Confidential App
client_uri: https://example.com
logo_uri: https://example.com/logo.png
redirect_uris:
- https://example.com/oauth/callback
token_endpoint_auth_method: client_secret_basic
scope: openid email profile
publicClient:
summary: Public Client Registration
description: Register a public client (no client secret)
value:
client_name: My Mobile App
client_uri: https://example.com
redirect_uris:
- myapp://oauth/callback
token_endpoint_auth_method: none
scope: openid email profile
minimalClient:
summary: Minimal Client Registration
description: Register a client with only required fields
value:
redirect_uris:
- https://example.com/callback
responses:
'201':
$ref: '#/components/responses/OAuth.DynamicClientRegistration'
'400':
$ref: '#/components/responses/OAuth.DynamicClientRegistrationError'
'422':
description: 'Unprocessable entity error. The dynamic client registration feature may not be enabled
for this instance.'
'500':
description: 'Internal server error. The authorization server encountered an unexpected condition
that prevented it from fulfilling the registration request.'
/oauth/token:
post:
summary: Get OAuth2 Token
description: "Exchange an authorization grant for OAuth2 tokens (access token, refresh token, and optionally ID token).\n\nThis endpoint implements the OAuth 2.0 Token Endpoint (RFC 6749) and OpenID Connect token endpoint.\nIt supports two grant types: `authorization_code` and `refresh_token`.\n\n#### Grant Types\n\n- **`authorization_code`**: Exchange an authorization code for tokens\n- **`refresh_token`**: Refresh an access token using a refresh token\n\n#### Authentication\n\n- **Confidential clients**: Must authenticate using one of the following methods:\n - HTTP Basic Authentication: `Authorization: Basic base64(client_id:client_secret)`\n - Client credentials in request body: Include `client_id` and `client_secret` in form fields\n - *Note: Both methods (`client_secret_basic` and `client_secret_post`) are treated equivalently*\n- **Public clients** (PKCE flow): No client secret required. Must provide `client_id` and `code_verifier` in request body.\n\n#### PKCE (Proof Key for Code Exchange)\n\nPublic clients and clients that cannot securely store a client secret must use PKCE (RFC 7636).\nWhen using PKCE:\n- Include `code_challenge` and `code_challenge_method` in the authorization request\n- Include `code_verifier` in the token request (instead of `client_secret`)\n\n#### Scopes\n\nAvailable scopes:\n- `openid` - Enables OpenID Connect features, returns an `id_token` in the response\n- `email` - User's email address\n- `profile` - Basic profile information (name, username, picture, etc.)\n- `public_metadata` - Clerk custom scope for public metadata\n- `private_metadata` - Clerk custom scope for private metadata\n\nDefault scopes (if not specified): `email profile`\n\n#### Token Lifespans\n\n- **Access token**: 1 day (86400 seconds)\n- **Refresh token**: 10 years\n- **ID token**: 1 day (86400 seconds)\n- **Authorization code**: 10 minutes (must be exchanged within this time)\n\n#### OpenID Connect\n\nWhen the `openid` scope is included in the authorization request, the token response will include\nan `id_token` field containing a signed JWT with user identity information per the OpenID Connect specification.\nThe `id_token` will be refreshed along with the access token when using the `refresh_token` grant type."
operationId: getOAuthToken
security:
- ClientCredentials: []
- {}
tags:
- OAuth2 Identity Provider
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required:
- grant_type
properties:
grant_type:
type: string
description: 'The grant type being used.
- `authorization_code`: Exchange an authorization code for tokens
- `refresh_token`: Refresh an access token'
enum:
- authorization_code
- refresh_token
code:
type: string
nullable: true
description: 'The authorization code received from the authorization endpoint.
**Required when `grant_type=authorization_code`**.'
redirect_uri:
type: string
nullable: true
description: 'The redirect URI used in the authorization request. Must match exactly.
**Required when `grant_type=authorization_code`**.'
code_verifier:
type: string
nullable: true
description: 'The PKCE code verifier that corresponds to the `code_challenge` sent in the authorization request.
**Required for public clients using PKCE with `grant_type=authorization_code`**.
Confidential clients using `client_secret` should not include this parameter.'
client_id:
type: string
nullable: true
description: 'The OAuth 2.0 client identifier.
**Required for public clients** (those not using HTTP Basic Authentication).
For confidential clients, can be provided here or via HTTP Basic Authentication.'
client_secret:
type: string
nullable: true
description: 'The OAuth 2.0 client secret.
**Required for confidential clients** (unless using HTTP Basic Authentication).
Public clients using PKCE should not include this parameter.'
refresh_token:
type: string
nullable: true
description: 'The refresh token issued to the client.
**Required when `grant_type=refresh_token`**.'
scope:
type: string
nullable: true
description: 'Space-separated list of scopes for the access token.
**Optional when `grant_type=refresh_token`**.
If provided, the requested scope must not exceed the scope originally granted.
If omitted, the same scope as originally granted will be used.'
examples:
authorizationCodeConfidential:
summary: Authorization Code - Confidential Client
description: Exchange an authorization code for tokens using a confidential client with client secret
value:
grant_type: authorization_code
code: clk_code_abc123xyz
redirect_uri: https://example.com/oauth/callback
client_id: client_abc123
client_secret: secret_xyz789
authorizationCodePKCE:
summary: Authorization Code - Public Client with PKCE
description: Exchange an authorization code for tokens using PKCE (public client, no client secret)
value:
grant_type: authorization_code
code: clk_code_abc123xyz
redirect_uri: https://example.com/oauth/callback
client_id: client_abc123
code_verifier: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
refreshToken:
summary: Refresh Token
description: Refresh an access token using a refresh token
value:
grant_type: refresh_token
refresh_token: clk_refresh_abc123xyz
client_id: client_abc123
client_secret: secret_xyz789
responses:
'200':
$ref: '#/components/responses/OAuth.Token'
'400':
$ref: '#/components/responses/OAuth.TokenError400'
'401':
$ref: '#/components/responses/OAuth.TokenError401'
'403':
description: Forbidden error, for example you are trying to use a satellite domain
/oauth/userinfo:
get:
summary: Get User Info After OAuth2 Flow
description: Get user info in exchange for a valid OAuth2 access token.
operationId: getOAuthUserInfo
security: []
tags:
- OAuth2 Identity Provider
responses:
'200':
$ref: '#/components/responses/OAuth.UserInfo'
'400':
$ref: '#/components/responses/ClerkErrors'
'401':
$ref: '#/components/responses/ClerkErrors'
'403':
$ref: '#/components/responses/ClerkErrors'
post:
summary: Get User Info After OAuth2 Flow
description: Get user info in exchange for a valid OAuth2 access token.
operationId: getOAuthUserInfoPOST
security: []
tags:
- OAuth2 Identity Provider
responses:
'200':
$ref: '#/components/responses/OAuth.UserInfo'
'400':
$ref: '#/components/responses/ClerkErrors'
'401':
$ref: '#/components/responses/ClerkErrors'
'403':
$ref: '#/components/responses/ClerkErrors'
/oauth/token_info:
post:
summary: Get Information for an Access or Refresh Token
description: Get information for an access or refresh token
operationId: getOAuthTokenInfo
security: []
tags:
- OAuth2 Identity Provider
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
token:
type: string
description: The value of the access or the refresh token
token_type_hint:
type: string
description: A hint about the type of the token submitted for introspection. Can be one of the following `access_token` and `refresh_token`
nullable: true
scope:
type: string
description: The granted scopes for the token to check against
nullable: true
required:
- token
responses:
'200':
$ref: '#/components/responses/OAuth.TokenInfo'
'401':
description: Unauthorized error, for example the provided client is invalid.
'422':
description: You are currently using the legacy OAuth 2.0 provider, please migrate to the new one via Clerk Dashboard.
/oauth/token/revoke:
post:
summary: Revoke OAuth2 Token
description: 'Revoke OAuth2 token by token.
#### Authentication
- **Confidential clients**: Must authenticate using HTTP Basic Authentication with Client ID as username and Client Secret as password in the Authorization header.'
operationId: revokeOAuthToken
security:
- ClientCredentials: []
tags:
- OAuth2 Identity Provider
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
additionalProperties: false
properties:
token:
type: string
description: The token to revoke.
nullable: false
token_type_hint:
type: string
description: A hint about the type of the token to be revoked.
nullable: true
enum:
- access_token
- refresh_token
responses:
'200':
description: Success, no content.
'400':
$ref: '#/components/responses/OAuth.TokenError400'
'401':
$ref: '#/components/responses/OAuth.TokenError401'
/v1/me/oauth/consent/{client_id}:
get:
summary: Get Consent Information
description: 'Returns the scopes for a given OAuth Application Client ID.
An optional `scope` query parameter can restrict the returned scopes to only those requested.
The OAuth application must have consent screen enabled.
'
operationId: getOAuthConsent
security:
- {}
- DevBrowser: []
tags:
- OAuth2 Identity Provider
parameters:
- in: path
name: client_id
required: true
schema:
type: string
description: The OAuth Application Client ID to get consent information for.
- in: query
name: scope
required: false
schema:
type: string
description: Optional space-separated list of scopes to restrict the response to only those requested.
responses:
'200':
$ref: '#/components/responses/OAuth.ConsentInfo'
'400':
$ref: '#/components/responses/ClerkErrors'
'401':
$ref: '#/components/responses/ClerkErrors'
'403':
$ref: '#/components/responses/ClerkErrors'
'404':
$ref: '#/components/responses/ClerkErrors'
'422':
$ref: '#/components/responses/ClerkErrors'
post:
summary: Submit OAuth2 Consent Decision
description: 'Submits the user''s consent decision for an OAuth2 authorization request.
This endpoint allows building custom consent portals as a replacement for
the default account-portal-rendered consent screen.
The OAuth application must have the consent screen enabled. On grant, the
flow continues just like the standard `/oauth/authorize` endpoint and
returns the appropriate redirect.
In addition to the fields documented below, the request body must
re-submit the standard OAuth2 authorize parameters from the original
`/oauth/authorize` request: `response_type`, `redirect_uri`, `scope`,
`state`, `nonce`, `code_challenge`, and `code_challenge_method`. These
are forwarded as-is to the authorize flow.
'
operationId: submitOAuthConsent
security:
- {}
- DevBrowser: []
tags:
- OAuth2 Identity Provider
parameters:
- in: path
name: client_id
required: true
schema:
type: string
description: The OAuth Application Client ID the consent decision applies to.
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
required:
- consented
properties:
consented:
type: boolean
description: 'The user''s consent decision. `true` grants the requested
scopes and continues the authorization flow; any other value
is treated as a denial and returns an `access_denied` error
in the redirect.
'
organization_id:
type: string
nullable: true
description: 'Optional. The organization to scope the issued token to. The
authenticated user must be a member of this organization. If
omitted, the user''s currently active organization is used.
'
responses:
'200':
description: Success for 'form_post' response mode
'302':
description: Redirect, no body.
'303':
description: Redirect, no body.
'400':
$ref: '#/components/responses/ClerkErrors'
'401':
$ref: '#/components/responses/ClerkErrors'
'403':
$ref: '#/components/responses/ClerkErrors'
'404':
$ref: '#/components/responses/ClerkErrors'
'422':
$ref: '#/components/responses/ClerkErrors'
components:
schemas:
OAuth.DynamicClientRegistrationError:
type: object
additionalProperties: false
description: 'Error response for OAuth 2.0 Dynamic Client Registration according to RFC 7591.
The error response uses OAuth 2.0 error response format.'
properties:
error:
type: string
enum:
- invalid_redirect_uri
- invalid_client_metadata
- invalid_software_statement
- unapproved_software_statement
description: 'Single ASCII error code string indicating the error type.
- `invalid_redirect_uri`: The value of one or more redirect_uris is invalid
- `invalid_client_metadata`: One or more client metadata fields is invalid
- `invalid_software_statement`: The software statement presented is invalid
- `unapproved_software_statement`: The software statement is not approved'
error_description:
type: string
description: 'Human-readable ASCII text description of the error used for debugging.
This is not meant to be displayed to the end-user.'
required:
- error
OAuth.ConsentInfo:
type: object
additionalProperties: false
properties:
oauth_application_name:
type: string
oauth_application_logo_url:
type: string
nullable: true
description: URL to the OAuth application's logo image
oauth_application_url:
type: string
nullable: true
description: URL to the OAuth application's website or homepage
client_id:
type: string
scopes:
type: array
items:
$ref: '#/components/schemas/OAuth.ScopeWithDescription'
required:
- oauth_application_name
- client_id
- scopes
ClerkError:
type: object
properties:
message:
type: string
long_message:
type: string
code:
type: string
meta:
type: object
required:
- message
- long_message
- code
OAuth.DynamicClientRegistrationResponse:
type: object
additionalProperties: false
description: 'Client information response after successful registration according to RFC 7591.
Contains the client identifier, client secret (for confidential clients), and
other client metadata.'
properties:
client_id:
type: string
description: 'Unique client identifier string assigned by the authorization server.
The client identifier is not a secret; it is exposed to the resource owner
and must not be used alone for client authentication.'
client_secret:
type: string
description: 'Client secret string. This value is used by confidential clients to
authenticate to the token endpoint. The client secret is omitted for
public clients (when token_endpoint_auth_method is "none").'
client_id_issued_at:
type: integer
format: int64
description: 'Time at which the client identifier was issued. The time is represented
as the number of seconds from 1970-01-01T00:00:00Z as measured in UTC.'
client_secret_expires_at:
type: integer
format: int64
description: 'Time at which the client secret will expire or 0 if it will not expire.
The time is represented as the number of seconds from 1970-01-01T00:00:00Z
as measured in UTC.'
client_name:
type: string
description: 'Human-readable string name of the client to be presented to the end-user
during authorization.'
client_uri:
type: string
format: uri
description: URL string of a web page providing information about the client.
logo_uri:
type: string
format: uri
description: URL string that references a logo for the client.
redirect_uris:
type: array
items:
type: string
format: uri
description: Array of redirection URI strings for use in redirect-based flows.
grant_types:
type: array
items:
type: string
description: 'Array of OAuth 2.0 grant type strings that the client can use at the
token endpoint.'
response_types:
type: array
items:
type: string
description: 'Array of the OAuth 2.0 response type strings that the client can use
at the authorization endpoint.'
scope:
type: string
description: 'Space-separated list of scope values that the client can use when
requesting access tokens.'
token_endpoint_auth_method:
type: string
enum:
- client_secret_basic
- client_secret_post
- none
description: 'Indicator of the requested authentication me
# --- truncated at 32 KB (44 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/clerk-com/refs/heads/main/openapi/clerk-com-oauth2-identity-provider-api-openapi.yml