OpenViking supports multi-tenant deployments where a single server hosts multiple isolated accounts. Each account contains one or more users, each with their own API key and role.
| Role | What it can do |
|---|---|
ROOT |
Server-wide access. Manage accounts and any user. Authenticate with the root API key. |
ADMIN |
Account-scoped. Can manage users within their own account. |
USER |
Account-scoped. Can read and write resources, run retrieval, manage sessions. |
All admin methods require the root API key.
Creates a new account and its first admin user. Returns the admin's generated API key.
const result = await huscarl.admin.createAccount("acme", "alice");
console.log(result.userKey); // alice's API keyLists all accounts on the server.
const accounts = await huscarl.admin.listAccounts();Permanently deletes an account and all its data.
await huscarl.admin.deleteAccount("acme");Registers a new user and returns their generated API key.
const result = await huscarl.admin.registerUser("acme", "bob", { role: "user" });
console.log(result.userKey); // bob's API keyLists all users in an account.
const users = await huscarl.admin.listUsers("acme");Removes a user from an account.
await huscarl.admin.removeUser("acme", "bob");Updates a user's role. Can be called by ROOT or by an ADMIN of the target account.
await huscarl.admin.setRole("acme", "bob", "admin");Rotates a user's API key, immediately invalidating the previous one.
const result = await huscarl.admin.regenerateKey("acme", "bob");
console.log(result.userKey); // bob's new API keycontexts.get() returns a HuscarlContext — the same resources, retrieval, sessions, and skills surface — with all requests scoped to the given account and user. No API call is made; it only sets the scoping headers.
The root client can act on behalf of any user by scoping to their account and user ID.
const ctx = huscarl.contexts.get({ account: "acme", user: "bob" });
await ctx.resources.list(); // requests are scoped to acme/bobWhen you have the user's own API key (e.g. after registerUser or regenerateKey), pass it as apiKey. The context then authenticates as that user directly — no root key is involved.
const { userKey } = await huscarl.admin.registerUser("acme", "bob");
const bobCtx = huscarl.contexts.get({ account: "acme", user: "bob", apiKey: userKey });
await bobCtx.resources.list();This is the right pattern for building multi-user backends where each user authenticates independently.
const ctx = await huscarl.contexts.create({
account: "acme",
user: "carol",
role: "user",
});
// carol is now registered and ctx is scoped to her