Endpoint Reference
All SingleSign endpoints require the platform_guid parameter to identify your platform. The base URL for all endpoints is https://api.singlesign.com.
Endpoint Summary
| Method | Path | Description | Auth Required |
|---|---|---|---|
GET | /.well-known/openid-configuration | OpenID Connect Discovery | No |
GET | /oauth/authorize | Start authorization flow | No |
POST | /oauth/token | Exchange code or refresh token for tokens | Client auth (confidential) or PKCE (public) |
GET | /oauth/userinfo | Get user profile claims | Bearer token |
GET | /oauth/jwks | JSON Web Key Set for token verification | No |
POST | /oauth/introspect | Validate a token | Client auth (Basic or POST) |
POST | /oauth/revoke | Revoke a token | No (but platform_guid required) |
1. Discovery
Retrieve the OpenID Connect configuration for your platform. Use this to dynamically discover all other endpoints and supported features.
GET /.well-known/openid-configuration?platform_guid=<guid>
Parameters
| Parameter | Location | Required | Description |
|---|---|---|---|
platform_guid | Query | Yes | Your platform identifier |
Example
curl "https://api.singlesign.com/.well-known/openid-configuration?platform_guid=YOUR_PLATFORM_GUID"
Response
{
"issuer": "https://api.singlesign.com",
"authorization_endpoint": "https://api.singlesign.com/oauth/authorize",
"token_endpoint": "https://api.singlesign.com/oauth/token",
"userinfo_endpoint": "https://api.singlesign.com/oauth/userinfo",
"jwks_uri": "https://api.singlesign.com/oauth/jwks",
"introspection_endpoint": "https://api.singlesign.com/oauth/introspect",
"revocation_endpoint": "https://api.singlesign.com/oauth/revoke",
"scopes_supported": ["openid", "profile", "email", "phone", "address", "offline_access"],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post", "none"],
"id_token_signing_alg_values_supported": ["HS512"],
"subject_types_supported": ["public"]
}
2. Authorize
Redirect the user's browser to this endpoint to start the authorization flow. The user will authenticate and consent, then be redirected back to your redirect_uri with an authorization code.
GET /oauth/authorize
Parameters
| Parameter | Location | Required | Description |
|---|---|---|---|
platform_guid | Query | Yes | Your platform identifier |
response_type | Query | Yes | Must be code |
client_id | Query | Yes | Your application's client ID |
redirect_uri | Query | Yes | Must exactly match a registered redirect URI |
scope | Query | Yes | Space-separated scopes (must include openid) |
state | Query | Recommended | Random string for CSRF protection |
code_challenge | Query | Conditional | PKCE code challenge (required for public clients) |
code_challenge_method | Query | Conditional | Must be S256 when code_challenge is present |
login_hint | Query | No | Email to pre-fill. When sent, SingleSign routes by account existence — existing account → sign-in, no account → sign-up — and the email field is locked (the user cannot change it) through the whole flow |
action | Query | No | login or register. Fallback page when no login_hint is sent or account existence can't be determined |
prompt | Query | No | login forces re-authentication even with an active session; select_account forces the account chooser; none never shows UI — the redirect carries error=login_required or error=consent_required when interaction would be needed |
max_age | Query | No | Maximum authentication age in seconds. A session authenticated longer ago than this forces a fresh sign-in (email pre-filled) |
first_name | Query | No | Optional sign-up pre-fill; editable by the user, ignored for existing accounts |
last_name | Query | No | Optional sign-up pre-fill; editable by the user, ignored for existing accounts |
phone_number | Query | No | Optional sign-up pre-fill; editable by the user, ignored for existing accounts |
Example
# Open this URL in the user's browser
https://api.singlesign.com/oauth/authorize\
?platform_guid=YOUR_PLATFORM_GUID\
&response_type=code\
&client_id=YOUR_CLIENT_ID\
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback\
&scope=openid%20profile%20email\
&state=abc123xyz\
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM\
&code_challenge_method=S256\
&action=register\
&login_hint=invitee%40example.com
Account chooser
If the user's browser already holds one or more SingleSign sessions, the authorize flow shows an account chooser ("Choose an account", similar to Google) instead of silently continuing with whichever account was signed in last. The user can continue as a listed account without re-entering their password, pick a signed-out account (email pre-filled), sign in as somebody else, or sign out. Platforms don't need to change anything to get this behavior; send prompt=select_account to force the chooser, or a locked login_hint to pin a specific account and skip it.
Success Response
Redirect to your redirect_uri:
https://app.example.com/callback?code=AUTHORIZATION_CODE&state=abc123xyz
Error Response
Redirect to your redirect_uri:
https://app.example.com/callback?error=access_denied&error_description=The+user+denied+the+request&state=abc123xyz
3. Token
Exchange an authorization code for tokens, or use a refresh token to get a new access token.
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization Code Exchange
| Parameter | Location | Required | Description |
|---|---|---|---|
grant_type | Body | Yes | authorization_code |
code | Body | Yes | The authorization code from the callback |
redirect_uri | Body | Yes | Same URI used in the authorize request |
client_id | Body | Yes | Your application's client ID |
code_verifier | Body | Conditional | PKCE code verifier (required if code_challenge was sent) |
client_secret | Body | Conditional | Required for confidential clients |
platform_guid | Body | Yes | Your platform identifier |
Example: Public Client (PKCE)
curl -X POST "https://api.singlesign.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE_HERE" \
-d "redirect_uri=https://app.example.com/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" \
-d "platform_guid=YOUR_PLATFORM_GUID"
Example: Confidential Client (with secret)
curl -X POST "https://api.singlesign.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTH_CODE_HERE" \
-d "redirect_uri=https://app.example.com/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" \
-d "platform_guid=YOUR_PLATFORM_GUID"
Refresh Token Exchange
| Parameter | Location | Required | Description |
|---|---|---|---|
grant_type | Body | Yes | refresh_token |
refresh_token | Body | Yes | The refresh token |
client_id | Body | Yes | Your application's client ID |
client_secret | Body | Conditional | Required for confidential clients |
platform_guid | Body | Yes | Your platform identifier |
Example: Refresh
curl -X POST "https://api.singlesign.com/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=REFRESH_TOKEN_HERE" \
-d "client_id=YOUR_CLIENT_ID" \
-d "platform_guid=YOUR_PLATFORM_GUID"
Success Response
{
"access_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...",
"id_token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "rt_xxxxxxxxxxxxxxxxxxxxxxxx",
"scope": "openid profile email"
}
Error Response
{
"error": "invalid_grant",
"error_description": "The authorization code has expired."
}
4. UserInfo
Retrieve the authenticated user's profile claims. The claims returned depend on the scopes granted to the access token.
GET /oauth/userinfo
Authorization: Bearer <access_token>
Parameters
| Parameter | Location | Required | Description |
|---|---|---|---|
Authorization | Header | Yes | Bearer <access_token> |
Example
curl -H "Authorization: Bearer ACCESS_TOKEN_HERE" \
"https://api.singlesign.com/oauth/userinfo"
Response
{
"sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"human_guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Jane Doe",
"given_name": "Jane",
"family_name": "Doe",
"email": "jane@example.com",
"email_verified": true,
"picture": "https://api.singlesign.com/avatars/jane.jpg"
}
Error Response
{
"error": "invalid_token",
"error_description": "The access token is expired or invalid."
}
5. JWKS
Retrieve the JSON Web Key Set used to verify token signatures. Cache the response and refresh it periodically or when signature verification fails.
GET /oauth/jwks?platform_guid=<guid>
Parameters
| Parameter | Location | Required | Description |
|---|---|---|---|
platform_guid | Query | Yes | Your platform identifier |
Example
curl "https://api.singlesign.com/oauth/jwks?platform_guid=YOUR_PLATFORM_GUID"
Response
{
"keys": [
{
"kty": "oct",
"alg": "HS512",
"use": "sig",
"kid": "singlesign-key-1"
}
]
}
6. Introspect
Validate a token and retrieve its metadata. This endpoint is intended for confidential clients (server-side applications) that need to verify a token's validity.
POST /oauth/introspect
Content-Type: application/x-www-form-urlencoded
Authorization: Basic <base64(client_id:client_secret)>
Parameters
| Parameter | Location | Required | Description |
|---|---|---|---|
token | Body | Yes | The access token or refresh token to introspect |
platform_guid | Body | Yes | Your platform identifier |
Authorization | Header | Yes | Basic auth with client_id:client_secret |
Example
curl -X POST "https://api.singlesign.com/oauth/introspect" \
-u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-d "token=ACCESS_TOKEN_HERE" \
-d "platform_guid=YOUR_PLATFORM_GUID"
Active Token Response
{
"active": true,
"sub": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"human_guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"client_id": "your-client-id",
"scope": "openid profile email",
"token_type": "Bearer",
"exp": 1740000000,
"iat": 1739996400
}
Inactive Token Response
{
"active": false
}
7. Revoke
Revoke an access token or refresh token. After revocation, the token can no longer be used. Always revoke refresh tokens when a user logs out.
POST /oauth/revoke
Content-Type: application/x-www-form-urlencoded
Parameters
| Parameter | Location | Required | Description |
|---|---|---|---|
token | Body | Yes | The access token or refresh token to revoke |
platform_guid | Body | Yes | Your platform identifier |
Example
curl -X POST "https://api.singlesign.com/oauth/revoke" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=ACCESS_OR_REFRESH_TOKEN_HERE" \
-d "platform_guid=YOUR_PLATFORM_GUID"
Response
The revoke endpoint returns 200 OK with an empty body on success, regardless of whether the token was valid. This prevents token existence probing.
HTTP/1.1 200 OK
Content-Length: 0
If the request is malformed:
{
"error": "invalid_request",
"error_description": "The 'token' parameter is required."
}
Error Response Format
All endpoints return errors in a consistent format:
{
"error": "error_code",
"error_description": "A human-readable description of the error."
}
See the Errors Reference for a complete list of error codes and troubleshooting tips.
Next Steps
- Scopes Reference — Claims returned by each scope.
- Errors Reference — Error codes and troubleshooting.
- Rate Limits — Per-endpoint rate limits.
- Tokens & Claims — JWT structure and validation.
Last updated: 2026-08-04
Related docs
- SingleSign Developer DocumentationLearn how to integrate SingleSign identity and authentication into your applications using OAuth 2.0 and OpenID Connect.
- the Error Reference docsComplete reference of SingleSign OAuth error codes, error response format, and troubleshooting tips for each error.
- Rate LimitsPer-endpoint rate limits, 429 response format, Retry-After header, and best practices for staying within limits.
- Firebase Auth comparisonSingleSign vs Firebase Authentication on lock-in, portability and consent, plus the cases where staying on Firebase is right.
- Auth0 comparisonSingleSign vs Auth0 compared on the difference that matters: who owns the account. A side-by-side table, then the three cases where each one is the right call.
- SaaS single sign-onSSO for SaaS applications using OAuth 2.0 and OpenID Connect: the flow to pick, the scopes to request, and a working integration path with SingleSign.
- authentication for startupsAuthentication for startups without a monthly-active-user meter: standards-based OAuth 2.0 sign-in you will not have to replace when the product finds traction.
- React authentication with PKCEReact authentication done the recommended way: Authorization Code with PKCE, and no client secret in your JavaScript bundle.