Skip to content
Markdown

Teams and the audit log

One Runtime account can have as many people as you need. They share its credit, sandboxes, other resources and keys. Each person has a role. Every change to members, keys, money and security settings is recorded in an audit log, with who made it, when, and from which address.

Every account starts with one person: its owner. Nothing changes until you invite someone.

Updated

On this page

Roles#

What they can do Owner Admin Developer Billing
See resources, usage, balance, keys and members yes yes yes yes
Start, run and delete sandboxes and other resources, using credit yes yes yes —
Create API keys and approve CLI connections yes yes yes —
Revoke or limit a key somebody else made yes yes — —
Have a key make, list and revoke keys over the API yes yes — —
Make a key account-wide, or limit it to its own again yes yes — —
Make, fill and delete compartments yes yes — —
Add credit and see payments yes yes — yes
Invite, remove and change the role of members yes yes — —
Read the audit log yes yes — —
Make someone an owner, or change or remove an owner yes — — —
  • An account always has at least one owner. To hand over an account, make the new person an owner, then leave or change your own role.
  • Anyone can leave an account, and anyone can revoke a key they made.
  • A key can never do more than the person who made it. Runtime checks that person's role on every request. If you change someone from developer to billing, their keys become read-only immediately.

Invite people#

Owners and admins invite people at Members. Choose Invite, enter an email address, choose a role, and choose Send invitation. To change someone's role later, pick the new one in their row.

  • The person gets an email with a link. The page also shows the link, so you can send it yourself.
  • The link works once, for seven days. It works only for someone who signs in with that email address. A forwarded link does not work for anyone else.
  • A new Runtime user signs up through the link and joins your account. A person with an existing account keeps it and joins your account too.
  • Sending an invitation again to the same address replaces the first one. Withdraw cancels an invitation that has not been used.
  • An invitation stays valid only while its sender could still send it. When the sender leaves, is removed, or loses the role that can invite, their open invitations are withdrawn.
  • An account can have 50 open invitations and send 25 in any 24 hours.

Several accounts#

A person can belong to several accounts, such as their own account and their company's account.

  • Website: choose the account from its name at the top of the sidebar. On a phone, the name sits at the left of the top bar. Runtime remembers the choice in this browser.
  • Connecting an agent: when you approve a connection or a key request, the approval page asks which account it is for.
  • CLI: every account you connect is saved on the machine.
Terminalnpx withruntime account add            # connect another account; choose it in the browsernpx withruntime account                # list them; * marks the one in usenpx withruntime account switch Acme    # use Acme for every command after this
  • SDKs and the API: a key belongs to one account, so use that account's key. GET /v1/me names the account and the role of the person who made the key.

Keys in a team#

Keys belong to the account, not to a person. Everyone who can see the account can see every key, and who made it, on the API keys page.

  • Each key is its own agent, so the audit log and the bill show which key did what.
  • A key sees and uses only the sandboxes and other resources its own agent made. A sandbox made with another key returns 404 to it, while a sandbox's name is still unique across the whole account.
  • An owner or admin can make a key account-wide. It sees and uses every sandbox, snapshot, image, volume, service and job in the account, whichever key made it. getOrCreate with a name another key holds returns that sandbox. To make one, choose "Everything in the account" when you create the key, use Make account-wide on a key's row, or run runtime keys create --account-wide. Only an owner or admin can approve that command. This is how services that share sandboxes work, as a Blaxel workspace key does.
  • An account-wide key still acts as its own agent. The audit log names it. A wake, extension or restart it asks for is billed to it and counts against its own daily limit, even on a sandbox another key made. Job secrets stay with the person who made the key. The secrets that sandboxes use belong to the account, for every key.
  • An account-wide key reaches the account only while the person who made it is an owner or admin. If that person changes to developer, the key sees only what it made again, from the next request. Developers and billing members cannot make or switch one. A read-only key already sees the whole account and is never account-wide.
  • An owner or admin can put a key in a compartment when making it. It then sees only what its compartment's keys made. No other key reaches in, except an account-wide one (compartments).
  • A full-access key of an owner or admin can make more keys over the API (run a swarm).
  • The person who made a key sets or changes its daily spending limit. Owners and admins can limit or revoke any key. A key can also change the keys it made (run a swarm).
  • When someone leaves or is removed, the keys they made are revoked in the same step. What they created, such as sandboxes, volumes and images, stays with the account.

Run a swarm#

One paid account has a coordinator and many workers. The coordinator holds a full-access key of an owner or admin (a wallet account's key is one). It makes one key per worker, each with its own daily cap.

Terminalruntime keys create --name worker-1 --daily-limit 5   # prints the key onceruntime keys ls                                       # each worker, with its spendruntime keys usage <keyId>                            # one worker in fullruntime keys update <keyId> --daily-limit 10          # give a worker more roomruntime keys revoke <keyId>                           # when the worker is done
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime(); // RUNTIME_API_KEYconst worker = await runtime.keys.create({ name: "worker-1", dailyLimitMicros: 5_000_000 });// hand worker.key to the worker, then later:console.log(await runtime.keys.usage(worker.keyId));await runtime.keys.update(worker.keyId, { dailyLimitMicros: 10_000_000 });await runtime.keys.revoke(worker.keyId);
Terminalcurl -sS https://api.withruntime.com/v1/keys -H "Authorization: Bearer ${RUNTIME_API_KEY}" \  -H "Idempotency-Key: worker-1" -H "Content-Type: application/json" \  -d '{"name":"worker-1","dailyLimitMicros":5000000}'curl -sS "https://api.withruntime.com/v1/usage?key=${KEY_ID}" -H "Authorization: Bearer ${RUNTIME_API_KEY}"curl -sS -X PATCH "https://api.withruntime.com/v1/keys/${KEY_ID}" -H "Authorization: Bearer ${RUNTIME_API_KEY}" \  -H "Content-Type: application/json" -d '{"dailyLimitMicros":10000000}'curl -sS -X DELETE "https://api.withruntime.com/v1/keys/${KEY_ID}" -H "Authorization: Bearer ${RUNTIME_API_KEY}"
  • POST /v1/keys takes name, and optionally access (full or read), reach (agent, the default, or account) and dailyLimitMicros. It can also take sandboxes and actions for a key limited to sandboxes. It returns the new key once. A retry with the same Idempotency-Key returns without the key.

  • PATCH /v1/keys/{id} changes a key's reach (agent or account) or dailyLimitMicros (null removes the limit), and returns the key as GET /v1/keys lists it. A key can change another key only to what it could make itself. It widens a key (account-wide, a larger limit, or no limit) only if it made that key, at any depth: account-wide only from an account-wide key, and the limits of the keys it made still add up to at most its own. Otherwise the request returns 403 forbidden. It can narrow any key it sees: back to its own agent, or a smaller limit. A key never changes itself. A key limited to sandboxes keeps its reach. Each change is in the audit log.

  • Each key is its own agent. A worker with reach agent sees only its own sandboxes, and its spend and audit rows are its own.

  • A key made by a key with reach agent can use what a sandbox needs (sandboxes, files, images, volumes, snapshots, previews and ports). It can also use the Apps and Functions its own agent made (create, list, deploy, roll back, delete), its own usage, and /v1/keys. Another worker's App returns 404, as for an id that does not exist. It can deploy an App or Function from an image only. A deploy that names a build comes from the account's repositories and is refused with 403 forbidden, before any build is read. Deploy builds with a key made on the website. It can request at most 2 minCopies, 2 spares and 20 maxCopies for an App. To make a larger App, use a key made on the website. It may set an App's releaseWatch to alert or rollback, never off. Turning it off would stop the owners hearing of a release that got worse, so that is refused with 403 forbidden. It cannot give an App or Function a name that one of the account's own Apps holds. Creating or renaming with such a name returns 409 name_taken. The account's own settings are refused with 403 forbidden, whatever its person's role: closing the account, webhooks, telemetry exports, the audit log, credit and billing, secrets, scheduled jobs and their secrets, domains, networks, builds and repositories. For those, use a key made on the website, or make this key account-wide.

  • The coordinator sees each worker's spend with runtime keys ls or GET /v1/usage?key=<keyId>. It sees its own spend, the keys it made at any depth, and any key its reads already reach.

  • Workers start from the coordinator's snapshots that carry the label share: made-keys. Set the label when you take the snapshot, or later with POST /v1/snapshots/{id}:update. Only snapshots the coordinator's key took itself count. Snapshots of other keys it can reach do not. The label is set on each snapshot itself and is never copied. A sandbox started from a shared snapshot, a fork's copies and kept snapshot, and a snapshot taken without labels of its own all leave out share: made-keys. So a copy you change and snapshot again is not shared unless you label it. A worker key made before this feature was released (see the changelog) does not reach shared snapshots. Make it again. Every key under the coordinator, at any depth, can create a sandbox from such a snapshot, memory or disk. It can do nothing else with it: it cannot list, read, change or delete it. A snapshot without the label returns 404 snapshot_not_found to them. So does a labelled snapshot of a sandbox that named its egress secrets (secrets on create). A copy would keep that list, and those secrets belong to the coordinator, not the worker. The coordinator can still start it. Sharing never crosses a compartment. Revoking the coordinator's key ends the sharing.

    TypeScriptconst snapshot = await sandbox.snapshot({ labels: { share: "made-keys" } });// in a worker, with its own key:const copy = await new Runtime({ apiKey: worker.key }).sandboxes.create({  snapshot: snapshot.id,});
  • Revoking stops a key within ten seconds. What its agent made keeps running until stopped.

  • Only a full-access key made by an owner or admin can do this. A read-only key, a selected-actions key, a developer's key or a key in a compartment cannot make, list or revoke keys.

  • A new key never has more than the key that made it. It can be account-wide only if the maker is account-wide. It keeps the maker's expiry and per-request cap. When the maker has a daily limit, every key it makes needs one. The daily limits of every live key under it, at any depth, add up to at most the maker's limit. A worker's own workers share its limit and never add to it. Keys can be made at most 8 deep. A read-only key cannot spend, so it takes no limit.

  • At most 100 live keys made this way per account, and 1,000 made in any 24 hours (quota_exceeded). Revoke workers' keys when done.

  • Each is in the audit log as key.created, by the making key's agent, with madeBy naming the key that made it.

A key limited to sandboxes

A key can be limited to a few sandboxes and to what it may do to them. Give it to something that needs one sandbox and should hold no key to the rest of the account. An example is a watcher that restarts a server when it stops responding.

Terminalruntime keys create --name watcher --sandbox <sandboxId> --actions get,create --daily-limit 2
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime(); // RUNTIME_API_KEYconst sandboxId = process.env.SANDBOX_ID!; // the sandbox to watchconst watcher = await runtime.keys.create({  name: "watcher",  sandboxes: [sandboxId],  actions: ["get", "create"],  dailyLimitMicros: 2_000_000,});
  • POST /v1/keys takes sandboxes (1 to 20 ids) and actions in place of access and reach. The actions are get (read the sandbox and its metrics), create (start, wake and restart it; it never makes a sandbox), stop (stop and pause it), exec (commands, processes and the interpreter), read_file and write_file.
  • It can call only those sandboxes' own routes, by id, and only for the actions it was given. Everything else returns 403 forbidden: other sandboxes, lists, deleting, resizing, forking, networks, sessions, secrets, jobs, keys, the account's settings and MCP.
  • It sees its sandboxes whichever key made them. The making key can name only sandboxes it acts on itself, outside every compartment.
  • Only create spends, so only a key with it takes a daily limit. It needs one when the making key has one.
  • runtime keys ls and GET /v1/keys show it with reach sandboxes, its sandboxes and its actions. It makes no keys.

Asked for in the browser

With no key on the machine, or with --browser, the same command asks an owner or admin to approve the key in the browser. runtime keys create does this for any key. Use it when a connector such as ChatGPT or Claude made the sandboxes and nobody holds a key to make one with. You can also use it to give an agent somewhere else a few sandboxes and nothing more:

Terminalruntime keys create --name helper --sandbox <id>,<id> --actions get,exec,read_file,write_file
  • It prints a link and a code. The approval page names each sandbox, what the key can do to it, and whether it can spend. The key goes to the terminal that asked, sealed to it, and is never shown anywhere else.
  • Only an owner or admin approves it, for any sandbox in the account outside every compartment, whichever key made it.
  • Without create, the key cannot start, wake or restart its sandboxes. It takes no daily limit, and it places no hold of its own. A running sandbox it reaches is billed to its owner as usual. Commands the key runs count as activity, so they keep the sandbox from pausing when idle. To limit that, give the sandbox a time limit (timeoutSeconds) or stop it when done.

Leaving and removing#

On Members, use the link at the end of the person’s row and confirm:

  • Leave takes you out of an account. The last owner cannot leave until there is another owner.
  • Remove takes someone else out. Admins remove developers, billing members and other admins; only an owner removes an owner.
  • Either way, the person loses access immediately, and their keys stop working. They can be invited back, with a new role if you like.
  • What they made stays in the account. Their stopped and paused sandboxes' disks, snapshots, volumes and images are kept on the account's credit, as anyone's are, until someone deletes them. The same holds when your directory suspends someone.

Emails#

Each person chooses which of Runtime's optional emails they get, for each account they are in, at Settings, Emails (withruntime.com/account/emails). Turning one off stops it for you only. Other owners still get theirs. The account's notices (GET /v1/notices, Usage & billing) and webhooks still include every one. Each of these emails also ends with a link that stops that kind for you, after asking.

Setting What it is
own-deletions A day before a sandbox is deleted at the date its own :retention chose, at most once a day
billing When the account's credit runs low or runs out
usage When the account has used 80% and all of the month's free usage
tips A few getting-started emails in your first days

Always sent, with no switch: sign-in links and invitations, a revoked key, replies in a support conversation, credit about to expire, service credits, and a warning before Runtime deletes something nothing pays for.

From code, a key reads and sets only its own person's emails, never anyone else's: GET /v1/account/emails, and POST /v1/account/emails:update with {"category": "own-deletions", "enabled": false}. In the CLI, use runtime account emails and runtime account emails own-deletions off. In MCP, runtime_account action emails reads them. Reading them needs a key that reads usage. Changing them needs a key with every action. A read-only or limited key returns 403 forbidden and changes nothing. A key with no person (a wallet account's) has none, and returns 403 no_person.

Closing the account#

An owner closes the account for good on the Close account page, linked at the foot of Members. It can also be done from the terminal with withruntime 0.7.0 or later:

Terminalruntime account close --confirm "Acme Inc"

Type the account's name exactly. runtime whoami shows it. The CLI and the API (POST /v1/account:close with {"confirm": "<name>"}, or runtime.account.close({ confirm }) in either SDK, from withruntime 0.7.0) need a key for every product made by an owner. No MCP tool closes an account.

Closing cannot be undone. Immediately:

  • every sandbox stops, and every snapshot, image, volume, volume backup, secret, egress secret and saved registry password is deleted;
  • custom domains, dedicated addresses and the private network are released, and webhooks, telemetry exports and the upstream proxy removed;
  • every key and CLI connection stops working, open invitations are withdrawn, and every member loses access.

Unspent credit from a purchase made in the last 15 days is refunded on request. Write to support@withruntime.com. Other credit, including granted and referral credit, is forfeited. Signing in again later starts a new, empty account.

Audit log#

Owners and admins read the audit log at Audit log. It records:

  • Members: joined, added, removed, left, and role changes; invitations sent and withdrawn
  • Keys: created and revoked, with the reason when Runtime revoked one; CLI connections and key requests approved or denied; spending limits set and removed
  • Credit: top-ups started, credit bought, granted, earned by referral, refunded, disputed, taken back or expired
  • Security settings: network rules, secrets created, updated, rotated, revealed and deleted (never the value), preview ports made public or private
  • Creations: every sandbox, volume, image, snapshot, service and job, with its name, labels and funding. Rules a sandbox is created with are part of its creation. A later change is recorded as a network rules entry. Funding is trial when the free usage pays for it. That covers a volume inside its 10 GiB, and a job on an account without credit. Such a job runs nothing until the account holds credit.
  • Sandboxes: every pause, wake, restart and stop, with who asked. For each one Runtime did itself, the entry says why: the sandbox sat idle, it reached its time limit, credit ran out, or a spending limit was hit.
  • Deletions: volumes, images, snapshots, services and jobs
  • The account: created, renamed, suspended and restored; the encryption key for its backups created, rotated (the old key made read-only) and destroyed
  • Single sign-on: connections added, changed and removed, domains verified, single sign-on required or not
  • Directory sync: SCIM tokens made and revoked, people your directory added, deactivated, reactivated or deleted, and the role each group gives

Each entry has the action; who did it (a person, a key, your directory, or Runtime itself, for things like a card payment); the time; the client's IP address; the request id; and whether it came through the website, the API or MCP. A call made by code inside one of your sandboxes also names that sandbox.

Entries are kept for at least 400 days. Nobody can edit an entry, and none is deleted before then. The page downloads the whole log, or one group of it, as a CSV file.

Read it from code

A key made by an owner or admin can read the log, if it has full access or is read-only. Entries are listed newest first, 50 at a time by default, up to 200.

Terminalcurl -H "Authorization: Bearer $RUNTIME_API_KEY" \  "https://api.withruntime.com/v1/audit?action=member.&limit=100"npx withruntime audit --action key.
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();const { events, next } = await runtime.audit.list({ action: "credit." });console.log(events.length, next);
Pythonfrom withruntime import Runtimewith Runtime() as runtime:    page = runtime.audit.list(action="credit.")    print(len(page["events"]), page["next"])
  • action is one action, like key.created, or a group ending in a dot: member., invitation., key., connection., limit., credit., network., secret., preview., resource., account., sso., scim..
  • next is the page's last entry. Pass it as before for older entries.
  • MCP: the runtime_audit_list tool, with the same filters.
  • A key made by a developer or billing member, or a key limited to selected actions, gets 403 forbidden.

Sign-in and single sign-on#

People sign in with an email link, with Google, or with your company's identity provider. Single sign-on works over SAML or OIDC with Okta, Microsoft Entra ID, Google Workspace and any other standard provider. SCIM directory sync adds, updates and removes people for you. Both are free on every account. See single sign-on for the setup.

  • An owner connects your identity provider for your email domain. The owner proves the domain with a DNS record. Only an owner can change single sign-on.
  • Anyone on that domain who signs in through your provider joins your account with the role you choose. Someone you removed does not come back that way.
  • Require single sign-on makes your provider the only way in for members. Owners can still use Google or an email link, so a broken provider cannot lock you out, and API keys keep working.
  • With SCIM, deactivating someone in your directory removes them from the account and revokes every key they made, immediately. Groups in your directory decide roles: admin, developer or billing, never owner.

Try it on your own work. Sign up, then paste the setup prompt into your coding agent.

Start free, no card

Was this page right?