Skip to content
Subako TypeScript SDK
Esc
navigateopen⌘Jpreview
On this page

Keys and access

Minting API keys with the permissions they need, and managing who is in the workspace.

An API key is how a backend authenticates. It belongs to one workspace and carries the permissions you minted it with, so a key for one job cannot be used for another.

Minting a key

const key = await subako.apiKeys.mint({
	label: "support backend",
	permissions: ["session.create", "session.read", "session.manage"],
	expires_at: "2027-01-01T00:00:00Z", // or null, for one that does not expire
});

if ("secret" in key) {
	store(key.secret); // shown once
}

The secret comes back once. The in check is there because a retried mint answers with a receipt instead — the key exists, and its prefix, label and permissions come back, but secret does not. Receipts explains when that happens and what to do about it.

const keys = await subako.apiKeys.list();
await subako.apiKeys.revoke(key.id);

The permissions

Mint the narrowest set that does the job. A backend that only starts sessions and reads them does not need agent.publish.

Permission Lets the key
workspace.read Read the workspace itself
agent.read List and read agents and their versions
agent.publish Publish a new agent version
agent.delete Delete an agent
session.create Create sessions and mint session tokens
session.read Read sessions, their logs and their sandboxes
session.manage Post input, cancel runs, resolve approvals, delete sessions
skill.read List and read skills
skill.manage Upload skills and push versions
vault.read List vaults
vault.manage Create, update and delete vaults
credential.read List the credentials in a vault
credential.manage Add and remove credentials
model_provider.read List the workspace’s model providers
model_provider.manage Add, update and remove them

A call the key lacks the permission for throws ForbiddenError, not UnauthorizedError — the credential was fine, the permission was not. See Errors.

Model providers

A workspace either uses the platform’s providers or brings its own keys.

const providers = await subako.modelProviders.list();

Each is either type: "platform", which publishes a catalog of models you can name in an agent config, or a workspace provider using your own credentials.

const provider = await subako.modelProviders.create({ /* provider details */ });
await subako.modelProviders.update(provider.id, { /* only what changes */ });
await subako.modelProviders.delete(provider.id);

An absent field on update leaves that part of the provider as it stands, so you can rotate a key without resending everything else.

Workspaces

const workspace = await subako.workspaces.create({ name: "support" });
await subako.workspaces.rename(workspace.id, { name: "support-eu" });

const members = await subako.workspaces.listMembers(workspace.id);
await subako.workspaces.addMember(workspace.id, { user_id: userId, role: "member" });
await subako.workspaces.changeMemberRole(workspace.id, userId, { role: "admin" });
await subako.workspaces.removeMember(workspace.id, userId);

Which workspace a call acts on comes from workspaceId — set on the client, or per call. An API key implies its own and refuses a header naming another. See Workspaces.

The organization

Above workspaces sits the organization: the people, their invitations, and the bill.

const org = await subako.organization.get();
await subako.organization.rename({ name: "Example Inc" });

await subako.organization.createInvitation({ email: "new@example.com", role: "member" });
const invitations = await subako.organization.listInvitations();
await subako.organization.revokeInvitation(invitationId);

const members = await subako.organization.listMembers();
await subako.organization.changeMemberRole(userId, { role: "admin" });
await subako.organization.removeMember(userId);

Usage and credits

const credits = await subako.organization.getCredits();
const usage = await subako.organization.listUsage({ limit: 100 });
const perWorkspace = await subako.workspaces.listUsage(workspaceId, { limit: 100 });

Both usage listings page like any other. See Pagination.

Who am I

const me = await subako.me.get();

Answers with the signed-in user and the organizations they belong to. It needs an accessToken, since an API key is not a person.

Was this page helpful?