Drıftstack docs
Docs

Team RBAC — invite, accept, act-as

This guide walks through the full lifecycle of a Driftstack team: the owner invites a member, the member accepts, and the member then runs sessions / manages resources scoped to the owner’s account.

You’ll need:

  • An owner account (already paying the subscription).
  • A second teammate’s email address.

Inviting, accepting and removing members happen in the Driftstack dashboard. Once a member is on the team, their programs work in the owner’s workspace through the API — see Team workspaces for the reference.

Step 1 — Invite a teammate (owner)

From the owner’s dashboard, navigate to Team in the sidebar + click Invite member. Fill in:

  • Email: the teammate’s email address. They’ll be able to accept only when signed in to a Driftstack account on this address.
  • Role:
    • member — read access to the owner’s persisted session metadata / profiles / audit log / etc. Live session state requires admin. Cannot make changes, and cannot list the owner’s API keys.
    • admin — full read + write. Can create sessions, manage webhooks and create API keys on the owner’s behalf.

The teammate receives an email with a 7-day accept link.

Step 2 — Accept the invite (teammate)

The teammate signs up at https://app.driftstack.io/signup/ using the invitee email address (must match exactly), then clicks the accept link from the invite email.

The link takes them to the dashboard’s /team/accept page, which checks that the signed-in account’s email matches the invitation and adds them to the team.

If the teammate already has an account (under the same email), they can sign in first and then click the accept link.

Step 3 — See the team you’re on (member)

The dashboard sidebar displays an Acting as picker that:

  • Lists the member’s own account (default) + each owner team.
  • Remembers your selection in this browser.
  • Auto-injects X-Driftstack-Account: acc_<owner-uuid> on every subsequent dashboard fetch.

The owner’s account id (acc_<owner-uuid>) is the value a member’s program sends. The owner can read it with GET /v1/whoami (account_id) and share it.

Step 4 — Act on the owner’s resources (member, admin role)

Once the member has a team, any /v1/* request can be scoped to the owner by passing X-Driftstack-Account: acc_<owner-uuid>:

# start an agent session OWNED by the team owner, through one of the
# OWNER's saved proxies; it counts against the OWNER's concurrent cap.
# The request counts against your rate limit first, then the owner's.
curl -X POST https://api.driftstack.dev/v1/agent-sessions \
  -H "Authorization: Bearer $MEMBER_KEY" \
  -H "X-Driftstack-Account: acc_owner-uuid" \
  -H "content-type: application/json" \
  -d '{ "mode": "ai", "proxy_id": "<owner-proxy-id>" }'

On hosted Driftstack every session runs through a saved proxy: a create with no proxy_id is refused with 422 proxy-required.

Role gating:

  • Persisted metadata reads on /v1/sessions (list and detail): both member and admin allowed.
  • Agent-session reads are the exception. GET /v1/agent-sessions requires admin even though it is a read: an agent session carries the model transcript and live control state, so the collection is not widened to read-only members. A member acting on an owner gets 403 there while the plain session list still works.
  • Live session state (GET /v1/sessions/:id/state): admin only. It returns the live session’s cookies and local storage; member gets 403 and the session is left untouched.
  • API key list: admin only. A member acting on an owner gets 403 instead of the owner’s key names and key prefixes.
  • Write endpoints (POST / PATCH / PUT / DELETE): admin role only. member gets 403.

Session and agent-session requests made on behalf of an owner count against two rate limits: yours first, then the owner’s. When you start or reopen an agent session for an owner, the first is a limit kept for you acting for that owner and sized by the owner’s plan, not your own plan’s limit. If the owner’s limit is exhausted you get a generic 429 with only Retry-After: the rate-limit headers are left out, and the request still counts against the first limit.

Endpoints that honor the header:

Resource Which routes
Sessions every /v1/sessions route you can call
Agent sessions every /v1/agent-sessions route, including /message. Note the collection READ needs admin — see above
Profiles every /v1/profiles route — not just CRUD, but trash, restore, purge, clone, export, import, trim
Profile snapshots every /v1/profile-snapshots route, and /v1/profiles/{id}/snapshots
Webhooks every /v1/webhooks route — GET / POST / PATCH / DELETE plus {id}/deliveries, {id}/rotate-secret, {id}/test, and delivery replay
Usage GET, /series
Saved proxies every saved-proxy route — an admin reads and writes the owner’s proxies, a member only lists them, as narrow rows
Recipes every /v1/recipes route — the recipe is saved from, and filed under, the owner’s workspace. Every one needs admin, reads included: a recipe is a saved copy of an agent session’s steps

A member reading the owner’s webhook deliveries gets last_response_excerpt as null. It is the reply of the owner’s endpoint, which can repeat an event that names an API key. An admin gets the excerpt.

If you are unsure about a route not listed here, the safe assumption is that it operates on your own account. GET /v1/whoami always describes the key that made the request.

Step 5 — Audit the team’s actions (owner)

When an endpoint emits an audit entry for a member’s action on the owner’s resources, that entry is written to the OWNER’s audit log with:

  • account_id: the owner.
  • actor_account_id: the member, when that endpoint records who acted.
  • actor_key_id: the member’s API key id, when that is recorded.

Not every endpoint currently writes an audit entry or records who acted. Treat these actor fields as a per-endpoint detail, not as a complete record of every team action.

So the owner sees, in their audit log, “Member [email protected] (acc_…) created session ses_… on this account at 2026-05-08 14:02 UTC”.

The owner reads the log, and downloads it as CSV, from the dashboard’s Audit log page.

A member reading the owner’s log (or its download) gets the API key entries without the key’s name, as for the key list; an admin and the owner see them.

A download holds at most the 10,000 newest entries. When the log is longer, the download is cut there: a JSON download says "truncated": true, and a program that fetches the export with an API key also gets the response header x-driftstack-export-truncated: true (false when nothing was cut). A CSV file has no field for this, so a program fetching CSV must check that header before treating the file as the whole log, and in the dashboard a JSON download is the one that tells you.

Removing a member (owner)

When a teammate leaves, the owner removes them from the dashboard’s Team page. The member is removed immediately; their X-Driftstack-Account header stops working on the next request. Their own account stays — only the team relationship is severed.

A team.member_removed audit entry lands on the owner’s log; the member is NOT separately notified by Driftstack (the owner can do that via their own channels).

Common patterns

Multiple admins on a team

A team can have any number of admin-role members, but every one of them is invited by the owner, from the owner’s own dashboard. The owner is always implicitly “admin” on their own team (no separate membership record).

Each admin has their own rate limit, but all admins acting on the same owner share the owner’s limit; adding admins never increases the owner’s capacity.

Read-only collaborators

Use role: 'member' for read-only access. Useful for:

  • Auditors / compliance reviewers (read the audit log + usage reports without write capability).
  • Junior teammates being onboarded (read session list/detail metadata + profiles without risk of accidentally minting a key or destroying a session).

Graceful key rotation across the team

API keys are rotated in the dashboard’s API keys page. The new plaintext is shown ONCE. If multiple teammates use the same key (e.g. across CI machines), the rotation flow is:

  1. Owner (or admin member) rotates → new key, 24h grace on the old.
  2. Teammates have 24h to swap deployments to the new key.
  3. After 24h the old key expires automatically.

A teammate can’t rotate a key with account_owner, admin or an admin:… scope — only the owner can. A key a teammate rotates counts as theirs: it is revoked when they leave the team, so if your own systems use it, rotate it again yourself before removing them.

Privacy note

A team member is a separate Data Subject from the owner. Their account email is processed under Privacy §3.1 on the same legal basis as any other Customer contact. Removing the member from the team does not delete their Driftstack account; only the membership relationship.

Next steps