Getting started
Authentication
Every request carries a bearer API key scoped to one organization. Keys are created in the console and can be read-only or write-scoped.
Bearer keys#
Create a key under Settings → API keys. The SDK sends it as Authorization: Bearer bah_… on every call. A key is bound to a single org — all runs, agents, and data it touches belong to that org.
const bahini = new BahiniClient({
apiKey: process.env.BAHINI_API_KEY!, // "bah_..."
});Scopes#
Keys are least-privilege by design. A read-onlykey can list and read (runs, agents, datasets, audit log) but is rejected on any write — creating agents, publishing data, kicking off runs. Give each integration the narrowest scope it needs, and rotate on your policy's schedule.
403 — surfaced as a BahiniApiError.Base URL#
Defaults to the hosted platform. For a self-hosted deploy, set baseUrl to your origin — the rest of the API is identical.
const bahini = new BahiniClient({
apiKey: process.env.BAHINI_API_KEY!,
baseUrl: "https://bahini.your-company.com",
});Errors#
Any non-2xx response throws a BahiniApiError carrying the HTTP status, a message, and the parsed error body. GET requests and idempotency-keyed POSTs are retried on transient network/5xx failures (linear backoff, 2 retries by default); 4xx is never retried.
import { BahiniApiError } from "@bahini/sdk";
try {
await bahini.runAgent("agent_123", { prompt: "..." });
} catch (err) {
if (err instanceof BahiniApiError) {
console.error(err.status, err.message, err.body);
} else {
throw err;
}
}Who am I?#
Verify a key and read its org + scope with getMe()— a cheap health check for your integration's startup.
const me = await bahini.getMe();
console.log(me.org.name, me.scope);