Get Started

Authentication

Theazo uses API keys for machine-to-machine access and RBAC roles for humans managing the platform. The two systems are independent — API keys authorize your SDK and backend calls; roles authorize dashboard and settings access.

API key types

Every platform gets two key environments. Both authenticate identically — the prefix determines whether the request provisions real compute or returns mock data.

Live keys

Live keys begin with th_live_. They provision real compute, record usage, and generate billing events. Use these only in production server-side code — never expose them in a browser bundle.

Test keys

Test keys begin with th_test_. They return realistic mock responses but never touch a provider, never record usage, and never generate billing events. Safe to use in CI, staging, and local development.

Live key

th_live_a1b2c3d4e5f6...
  • + Provisions real compute
  • + Records usage and billing
  • + Fires webhooks
  • — Never expose client-side

Test key

th_test_a1b2c3d4e5f6...
  • + Safe in CI / staging
  • + Returns realistic mock data
  • + No billing impact
  • — No real compute provisioned

SDK usage

Pass your key to the constructor. The SDK attaches it as a Bearer token on every request automatically. The same constructor accepts both live and test keys.

theazo.ts
import { Theazo } from 'theazo'

const theazo = new Theazo({
  apiKey: process.env.THEAZO_API_KEY!, // th_live_... or th_test_...
})

Direct API usage

If you are calling the REST API directly, supply the key in the Authorization header as a Bearer token. All endpoints require authentication.

curl https://api.theazo.com/v1/sessions \
  -H "Authorization: Bearer th_live_..." \
  -H "Content-Type: application/json"
GET/v1/sessions

List sessions for the authenticated platform. Requires a valid API key in the Authorization header.

Response

{ sessions: Session[], total: number }

Example

bash
curl https://api.theazo.com/v1/sessions \
  -H "Authorization: Bearer th_live_..." \
  -G \
  --data-urlencode "limit=20"

Managing keys

API keys are managed from Settings → API Keys in the dashboard. You can create multiple keys (e.g., one per service), label them, and revoke individual keys without rotating others.

The full key is shown exactly once — at creation time. After that, only the prefix (e.g., th_live_a1b2...) is visible. Store keys in a secrets manager immediately after creation.

# Rotate a key safely:
# 1. Create a new key in Settings → API Keys
# 2. Deploy with the new key
# 3. Revoke the old key once traffic confirms the new one is active
Never expose live API keys in client-side code, public repositories, or build logs. Keys embedded in a browser bundle give anyone full access to your platform account. Always load them from server-side environment variables.

Authentication errors

A missing or invalid key returns a 401 with error code auth/invalid_key. A revoked key returns auth/key_revoked. Always include the requestId when contacting support.

error-handling.ts
import { TheazoError } from 'theazo'

try {
  const session = await theazo.sessions.forUser('user_123')
} catch (err) {
  if (err instanceof TheazoError) {
    console.log(err.code)      // 'auth/invalid_key'
    console.log(err.status)    // 401
    console.log(err.requestId) // 'req_...' — include in support tickets
  }
}

Role-Based Access Control (RBAC)

Every Theazo organization has members with roles. Roles control what actions a person can take via the dashboard and Next.js API routes. RBAC is for humans — not machines. When your backend calls the Theazo API with an API key, the key itself is the authorization and RBAC does not apply.

Roles

owner

Full control. One per org (transferable). Cannot be removed by anyone. Must transfer ownership before leaving.

admin

Everything except: delete org, transfer ownership, or remove other admins. Can manage team, keys, billing, providers, secrets.

member

Operational access. Can create sessions, run agents, manage their own secrets. Cannot manage team or billing.

viewer

Read-only. Can view dashboard, usage, logs, and billing. Cannot create, modify, or delete anything.

Permission matrix

PermissionOwnerAdminMemberViewer
Organization
Delete organization
Transfer ownership
Update org settings
Team
Invite members
Change member roles
Remove members
View team
API Keys
Create / revoke API keys
View keys (prefix only)
Billing
Change plan / set budgets
View billing & usage
Secrets
Create / update secrets
Delete secrets
View secret names
Providers
Configure BYOI providers
View provider config
Sessions & Agents
Create / manage sessions
Run agents
View sessions / agents
Observability
View logs / traces / metrics
Configure webhooks

Management plane vs data plane

Theazo has two distinct authorization planes. Understanding the distinction avoids confusion when reasoning about who can do what.

Management plane

Dashboard, Settings, Next.js API routes (/api/*). Authorized via Supabase session cookie. RBAC roles enforced here.

  • + Invite / remove team members
  • + Create / revoke API keys
  • + Configure BYOI providers
  • + View billing, set budgets

Data plane

SDK calls, Hono API routes (/v1/*). Authorized via th_live_* / th_test_* API key. RBAC does not apply here.

  • + Create sessions, run agents
  • + Read usage and logs
  • + Full platform access scoped to the key
  • — RBAC roles have no effect
API keys are scoped to an organization, not to an individual member. If an admin creates a key and is later removed from the org, the key continues to work — keys track their creator for audit purposes only. If you want to scope what different developers can do with keys, create separate keys and distribute them selectively.

Team management

Manage your team from Settings → Team in the dashboard. Owners and admins can invite members, change roles, and remove members. All role changes take effect immediately.

Invite a member

POST/api/team

Invite a user to the organization. The invited user will see the org in their dashboard after accepting. Pending members have no access until they accept. Invites expire after 7 days.

Parameters

userIdstringrequiredThe Supabase user ID of the person to invite.
rolestringRole to assign: 'admin', 'member', or 'viewer'. Defaults to 'member'. Cannot invite as 'owner'.

Response

{ id, userId, role, invitedAt, pending: true }

Example

bash
curl https://your-dashboard.com/api/team \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "userId": "usr_abc123", "role": "member" }'

List members

GET/api/team

List all members of the organization including pending invites. Returns the caller's current role and user ID for client-side RBAC rendering.

Response

{ members[], currentUserId, currentRole }

Example

bash
curl https://your-dashboard.com/api/team

Change a member's role

PATCH/api/team/:memberId

Change the role of an existing member. Owner and admin only. Cannot change the owner's role — use the transfer endpoint instead. Cannot promote to 'owner' via this endpoint.

Parameters

rolestringrequiredNew role: 'admin', 'member', or 'viewer'.

Response

{ id, role }

Example

bash
curl https://your-dashboard.com/api/team/mem_abc123 \
  -X PATCH \
  -H "Content-Type: application/json" \
  -d '{ "role": "admin" }'

Remove a member

DELETE/api/team/:memberId

Remove a member from the organization. Owner and admin only. The removed user loses access immediately. Cannot remove the owner — transfer ownership first.

Response

{ ok: true }

Example

bash
curl https://your-dashboard.com/api/team/mem_abc123 \
  -X DELETE

Transfer ownership

POST/api/team/transfer

Transfer the owner role to another member. Only the current owner can call this. The current owner becomes admin. The new owner becomes owner. This action cannot be undone without the new owner's cooperation.

Parameters

newOwnerIdstringrequiredThe org_members.id of the member to promote to owner.

Response

{ ok: true }

Example

bash
curl https://your-dashboard.com/api/team/transfer \
  -X POST \
  -H "Content-Type: application/json" \
  -d '{ "newOwnerId": "mem_xyz789" }'

Edge cases

These constraints are enforced server-side. The dashboard prevents these actions in the UI, but the API also returns an error if you attempt them directly.

Owner cannot be removed

The owner role cannot be removed or changed via PATCH /api/team/:memberId. To leave the org, the owner must first transfer ownership via POST /api/team/transfer, then they can remove themselves as admin.

Admin cannot remove another admin

Admins can remove members and viewers. They cannot remove other admins — only the owner can. This prevents admin-vs-admin privilege conflicts.

Cannot promote to owner via role change

PATCH /api/team/:memberId accepts 'admin', 'member', or 'viewer'. Passing 'owner' returns 400 invalid_role. Use POST /api/team/transfer instead.

Pending invites block re-invite

If a user already has a pending invite or is already a member, POST /api/team returns 409 already_member. The user must accept or the invite must expire (7 days) before re-inviting.

Single-person org

Most orgs start with one person. All features work — RBAC returns 'owner' for every check. No overhead until a second member is added.

Ownership transfer is irreversible without the new owner's cooperation. Before transferring, confirm the target user has accepted their invite (acceptedAt is not null). Transferring to a pending member returns 400 transfer_to_pending.
Was this page helpful?
Ask anything...⌘I