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.
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"/v1/sessionsList sessions for the authenticated platform. Requires a valid API key in the Authorization header.
Response
{ sessions: Session[], total: number }Example
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 activeAuthentication 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.
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
ownerFull control. One per org (transferable). Cannot be removed by anyone. Must transfer ownership before leaving.
adminEverything except: delete org, transfer ownership, or remove other admins. Can manage team, keys, billing, providers, secrets.
memberOperational access. Can create sessions, run agents, manage their own secrets. Cannot manage team or billing.
viewerRead-only. Can view dashboard, usage, logs, and billing. Cannot create, modify, or delete anything.
Permission matrix
| Permission | Owner | Admin | Member | Viewer |
|---|---|---|---|---|
| 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
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
/api/teamInvite 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
curl https://your-dashboard.com/api/team \
-X POST \
-H "Content-Type: application/json" \
-d '{ "userId": "usr_abc123", "role": "member" }'List members
/api/teamList 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
curl https://your-dashboard.com/api/teamChange a member's role
/api/team/:memberIdChange 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
curl https://your-dashboard.com/api/team/mem_abc123 \
-X PATCH \
-H "Content-Type: application/json" \
-d '{ "role": "admin" }'Remove a member
/api/team/:memberIdRemove 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
curl https://your-dashboard.com/api/team/mem_abc123 \
-X DELETETransfer ownership
/api/team/transferTransfer 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
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.
acceptedAt is not null). Transferring to a pending member returns 400 transfer_to_pending.