Connect a product
Let a workspace owner connect your product to Buddhi without copying a key.
The connect flow is how a product gets Buddhi credentials for a customer's workspace. The owner clicks Connect Buddhi in your product, approves in Buddhi, and is sent back. Your server receives a strict credential set. Nobody sees or pastes a key.
It is standard OAuth 2.1 authorization code with PKCE.
What the owner sees
A Buddhi page naming your product and the site it will return to, with a checkbox for each scope they can share. Publishable is ticked by default; nothing else is. They choose, then approve.
Only the workspace owner can approve. Anyone else is told so.
1. Register your product (once)
POST /oauth/register
curl https://<your-buddhi-host>/oauth/register \
-H "Content-Type: application/json" \
-d '{"client_name": "Burrito AI", "redirect_uris": ["https://app.yourproduct.com/connect/buddhi/callback"]}'
{ "client_id": "3f6a…", "client_name": "Burrito AI", "redirect_uris": ["https://app.yourproduct.com/connect/buddhi/callback"] }
Keep the client_id. Redirect URIs must be https and are matched exactly. client_name is what the owner sees and what the connection is called in Buddhi.
2. Send the owner to Buddhi
Create a PKCE verifier and challenge, keep the verifier and a state value in the owner's session, and redirect to:
https://<your-buddhi-host>/oauth/authorize
?response_type=code
&client_id=<client_id>
&redirect_uri=<one of your registered URIs>
&scope=api
&code_challenge=<base64url(sha256(verifier))>
&code_challenge_method=S256
&state=<random value>
scope=api is what makes this a product connection.
3. Receive the code
After approval Buddhi redirects to your redirect_uri with code and state. Check that state matches. If the owner cancels you get error=access_denied instead.
4. Exchange the code
POST /oauth/token
curl https://<your-buddhi-host>/oauth/token \
-d grant_type=authorization_code \
-d code=<code> \
-d client_id=<client_id> \
-d redirect_uri=<the same redirect URI> \
-d code_verifier=<verifier>
{
"access_token": "bat_…",
"token_type": "Bearer",
"expires_in": 600,
"refresh_token": "crtx_…",
"signing_secret": "bss_…",
"scope": "api",
"buddhi_scopes": ["publishable"]
}
| Field | What to do with it |
|---|---|
access_token | The bearer for API calls. Valid for expires_in seconds |
refresh_token | Store encrypted. Send it only to the token endpoints to get new access tokens |
signing_secret | Store encrypted. Sign every request with it, see Authentication |
buddhi_scopes | The scopes the owner approved. Show them in your settings screen |
A code works once and expires after ten minutes.
5. Refresh the access token
When the access token expires, get a new one with either endpoint. Both must be signed.
POST /oauth/token grant_type=refresh_token&refresh_token=crtx_…
POST /api/v1/token Authorization: Bearer crtx_…
The refresh token does not change and does not expire unless the owner revokes the connection.
Disconnecting and reconnecting
- The owner can revoke the connection in Buddhi under Gateway & Agents. Your next call returns
401 invalid_key; treat that as "disconnected" and ask them to connect again. - When the same product is connected again by the same owner, the earlier connection is revoked. There is one live connection per product.
- To change the scopes, connect again and tick a different set.
Storing what you receive
Store only the refresh token, the signing secret and the list of scopes, encrypted, on your server, per customer workspace. Access tokens can be kept in memory. Never send any of them to a browser.