Authentication

Every Saaya API call is authenticated with a bearer token and scoped to a single organization. There are no anonymous endpoints, no implicit org context, and no cookie-based auth on the API surface.

API keys

API keys are minted from `Settings → API Keys` in the dashboard at app.saaya.ai. Two prefixes are issued: `sk_live_` for production and `sk_test_` for sandbox traffic. Keys carry the org id they were minted under and inherit the role of the minting user.

request.sh
curl https://api.saaya.ai/api/v1/agents \
  -H "Authorization: Bearer sk_live_..." \
  -H "X-Organization-Id: org_2N3rH..." \
  -H "Content-Type: application/json"

Never embed live keys

Saaya keys grant org-wide access. Keep them on the server. For browser surfaces (chat widget, in-app embed), exchange a live key for a short-lived session token via the SDK before handing anything to the client.

The X-Organization-Id header

Saaya is multi-tenant by default. Even with a valid bearer token, every request must declare which organization it acts on via `X-Organization-Id`. The backend rejects mismatches at the request-context layer, there is no "default org" fallback.

Scopes

Keys can be minted with one of four scopes that mirror the org-role model: `read`, `agents:write`, `sessions:write`, and `admin`. Most production integrations use `agents:write` + `sessions:write`. Reserve `admin` for back-office automation that needs to mint keys or rotate webhooks.

  • `read`, list and inspect agents, sessions, knowledge bases, campaigns.
  • `agents:write`, create, update, publish, rollback, delete agents and KBs.
  • `sessions:write`, start sessions, stream messages, dispatch test calls, run campaigns.
  • `admin`, mint keys, rotate webhook secrets, edit RBAC, manage org settings.

SDK helpers

The TypeScript and Python SDKs read `SAAYA_API_KEY` and `SAAYA_ORG_ID` from the environment by default, so you only configure them in one place.

client.ts
import { Saaya } from "@saaya/sdk";

// Reads SAAYA_API_KEY + SAAYA_ORG_ID from process.env automatically.
export const saaya = new Saaya();

// Or pass them explicitly:
export const saaya2 = new Saaya({
  apiKey: process.env.SAAYA_API_KEY,
  orgId:  process.env.SAAYA_ORG_ID,
});

Rotation

Treat keys like passwords. Rotate them every 90 days, on any team-membership change, and immediately on suspected exposure. Saaya supports overlapping keys, mint the new key, deploy it, then revoke the old key, so you can rotate with zero downtime.

rotate.ts
// 1. Mint a new key (keep the old one alive for now).
const fresh = await saaya.apiKeys.create({ scope: "agents:write" });

// 2. Roll fresh.value into your secret manager and redeploy.

// 3. Revoke the old key once nothing in production references it.
await saaya.apiKeys.revoke(oldKeyId);

Login lives elsewhere

These are programmatic keys for the API. Human sign-in to the dashboard happens at app.saaya.ai/auth and is unrelated, the marketing site is fully public and never asks for a password.
Was this page helpful?