login.busha.io) and the resource API (api.busha.io). OAuth app management — creating apps, revealing secrets, editing redirect URIs — is dashboard-only at app.busha.io.
GET /oauth2/auth
Browser redirect — this is where you send the user’s browser to start authorization. Never call this server-to-server.
Required query parameters:
Success: Redirects to your callback with
?code=...&state=...
User cancelled: Redirects with ?error=access_denied&state=...
POST /oauth2/token
Server-to-server. Authenticate with HTTP Basic using client_id:client_secret. Never call this from the browser.
Authorization code → tokens
Refresh token → new pair
id_tokenis returned only whenopenidis in the granted scopes.refresh_tokenis returned only whenoffline_accessis granted.redirect_urimust exactly match a registered URI.- Authorization codes are single-use and expire in 10 minutes.
- Token exchange is not idempotent — if your callback handler runs twice, the second call returns
invalid_grant.
authorization_code (with PKCE-S256) and refresh_token only. Implicit, resource-owner password, and client_credentials are not supported.
POST /oauth2/revoke
Revoke an access or refresh token. Call this when a user disconnects your integration.
200 with an empty body regardless of whether the token was valid — this is intentional to avoid leaking token validity information.
Revoking a refresh token kills future refreshes immediately but does not invalidate a currently-issued access token. The access token continues to validate until
exp.GET /.well-known/openid-configuration
The OIDC discovery document. Contains the canonical issuer string and the URLs of all protocol endpoints.
issuer value from this document at startup and pin your JWT validation against it. Do not hardcode the issuer string.
GET /.well-known/jwks.json
The public key set used to verify JWT signatures.
kid in a JWT header that is not present in your cache.