OAuth apps
OAuth 2.1 apps
Let people connect your app to their own Dhanu workspace, authorization code with PKCE, a consent screen, per-user tokens, refresh and revocation.
An API key acts for the workspace that minted it. An OAuth app acts for a person who signed in and said yes: they see what your app asks for, pick one of their workspaces, and your app receives tokens scoped to exactly that. Dhanu is an OAuth 2.1 authorization server: authorization code with PKCE only, no implicit or password grants, exact redirect-URI matching, refresh-token rotation.
1. Register the app
In the developer console (Developers → OAuth apps) register an app under a project.
You choose its redirect URIs (https, http://localhost for development, or a
custom scheme for native apps), the scopes it may ever ask for, and whether it
is a server-side app (gets a client secret, shown once) or a native /
single-page app (no secret, PKCE alone protects the exchange).
The app starts unverified. Unverified apps can ask for the everyday scopes; sensitive ones, writing files, reading files, searching the brain, running workflows, rendering video, need verification.
2. Send the person to authorize
https://app.dhanu.ai/oauth/authorize
?response_type=code
&client_id=dhanu_oc_…
&redirect_uri=https://app.example.com/oauth/callback
&scope=openid%20offline_access%20tasks.create%20tasks.read
&state=…
&code_challenge=…
&code_challenge_method=S256
They sign in (social, passkey, MFA, the same sign-in as the app), see your app’s
name and each scope in plain words, choose a workspace, and approve. Dhanu redirects
back to redirect_uri with code and your state. A refusal returns
error=access_denied. Scopes are the same ids the API catalogue
uses, plus openid, profile, email and offline_access (which is what earns a
refresh token).
3. Exchange the code
curl -X POST https://api.dhanu.ai/api/v1/oauth/token \
-u "dhanu_oc_…:dhanu_ocs_…" \
-d grant_type=authorization_code \
-d code=dhanu_ac_… \
-d redirect_uri=https://app.example.com/oauth/callback \
-d code_verifier=…const response = await fetch("https://api.dhanu.ai/api/v1/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
grant_type: "authorization_code",
client_id: process.env.DHANU_CLIENT_ID,
client_secret: process.env.DHANU_CLIENT_SECRET,
code,
redirect_uri: "https://app.example.com/oauth/callback",
code_verifier: verifier,
}),
});
const { access_token, refresh_token, expires_in } = await response.json();import requests
tokens = requests.post(
"https://api.dhanu.ai/api/v1/oauth/token",
auth=(CLIENT_ID, CLIENT_SECRET),
data={
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "https://app.example.com/oauth/callback",
"code_verifier": verifier,
},
).json() The response is the standard shape: access_token (dhanu_at_…, valid for one
hour), token_type: Bearer, expires_in, scope, and refresh_token
(dhanu_rt_…, valid for 30 days) when offline_access was granted. Client
credentials go in an HTTP Basic header or in the body; a public client sends only
client_id. Codes are single use and expire after ten minutes.
4. Call the API as the user
An access token is a bearer token on the public API, exactly like an API key:
curl https://api.dhanu.ai/api/pub/v1/me -H "Authorization: Bearer dhanu_at_…"
Every SDK accepts it in place of a key, new Dhanu(accessToken). The token
carries the workspace the person chose and only the scopes they approved; a call
outside them answers 403 with api_key_operation_scope. Credits are spent from
their workspace, and usage is attributed to your app’s project in the request
log.
5. Refresh and revoke
curl -X POST https://api.dhanu.ai/api/v1/oauth/token \
-u "dhanu_oc_…:dhanu_ocs_…" -d grant_type=refresh_token -d refresh_token=dhanu_rt_…
curl -X POST https://api.dhanu.ai/api/v1/oauth/revoke \
-u "dhanu_oc_…:dhanu_ocs_…" -d token=dhanu_at_…
Refreshing rotates: the old access and refresh tokens stop working the moment the
new pair is issued. revoke takes either token. People can also cut an app off
themselves from Settings → Connected apps, which revokes every token and the
consent; the next authorize shows the consent screen again.
Discovery
GET https://api.dhanu.ai/api/v1/oauth/.well-known/oauth-authorization-server
returns RFC 8414 metadata, endpoints, supported grants and scopes, for clients
that configure themselves.