Accounts & access
Accounts, roles, members, project access, groups, object grants and custom roles: who can do what in Kortix.
An account holds projects and the people who work in them. Every person holds one account role, and a project role on each project they work in. This page is for the owners and admins who invite a team and decide who can do what.
Invite a teammate
Open Account settings → Members and select Invite. From a terminal:
kortix members invite alice@example.com --role member --project <project_id>:member--project gives the project role in the same call. Step 3 still applies.
Give them a project
Open Account settings → Projects, pick the project, and select Grant access. Pick a role: Manager or Member.
Choose their agents
Give them at least one agent. In the Grant access dialog, set Agents to All agents or Only these…. From a terminal:
kortix access grant --user alice@example.com --agent kortix # one person
kortix access grant --everyone --agent kortix # every project memberWithout an agent grant, a member cannot start a session: the API answers 403 with “You don’t have access to any agent in this project.”
Owners and admins reach every project without a grant.
Accounts
Kortix creates a personal account when you sign up. You are its owner and its super-admin. Invite people to work in it with you.
- Several accounts, one login. One login can belong to many accounts. Each account keeps its own projects, members and settings.
- Switch. Open the project menu → Switch Project. It lists your projects grouped by account. In the CLI,
kortix accounts use <slug|id>sets the account that account-scoped commands act on. - Create a team account first. The account Kortix creates at sign-up is personal. It cannot hold SAML SSO (
403sso_personal_account), and a project cannot move to another account. For a team, select Create an account… before you create projects. - Create another. Open the project menu → Switch Project → Create an account…. The creator becomes owner and super-admin. A self-hosted instance can restrict this to its server admin; the API then returns
403account_creation_restricted. See Self-hosting. - Rename. Account settings → Settings. Needs
account.write.
kortix accounts ls # the accounts you belong to
kortix accounts use # pick the active account (interactive)
kortix accounts current # print the active account
kortix accounts info # one account in detail
Account settings
Open the project menu → Switch Project → Account settings.
| Sidebar group | Section | What it holds |
|---|---|---|
| — | Settings | The account name. The Security group: Require MFA, session lifetime and idle timeout, live member sessions, and Admins can open every session. The Automations group: Pause all automations; see Pause and limits. |
| — | Branding | Logo, icon, favicon and product name. See Branding. |
| — | Git | GitHub App installations. See Git. |
| — | API keys | Service-account keys and key rules. See Sign-in, SSO & API keys. |
| Access | Members | People, their account roles, pending invites. |
| Access | Groups | Groups and their members. |
| Access | Projects | Who reaches each project, at which role, with which agents. |
| Access | Roles | Built-in and custom roles. |
| Access | Identity | SAML single sign-on and SCIM. See Sign-in, SSO & API keys. |
| Access | Audit log | The account’s audit trail. See Audit log. |
| Access | Help | How access works in this account. |
| Billing | Plan, Usage | Plan, wallet, spend and the credit ledger. See Plans & credits. |
Account roles
Each person holds exactly one account role: owner, admin or member.
| Role | Can do |
|---|---|
owner |
Everything an admin can do, plus: delete the account (account.delete), grant or revoke super-admin (member.super_admin.grant), and grant or change the owner role. |
admin |
Rename the account and change its security settings, except Admins can open every session. Change the plan and payment method (billing.write). Invite, remove and change the role of members. Manage groups, roles, assignments, service-account keys and OAuth clients. Create projects. Read the audit log and the plan. |
member |
See the account, its plan and its billing ledger (billing.read). In the member list they see only themselves, and they see no groups (see Who sees the member list). Create, list and revoke their own personal access keys. Work only in the projects a grant gives them. |
- Members cannot create projects and cannot change billing. Owners and admins hold
billing.write. Only an owner holdsaccount.delete. - Owners and admins are manager on every project in the account. This is a rule of the account role, not a grant, and a project grant cannot lower it. To limit an owner or admin on one project, change their account role to
memberfirst. - Promotion removes project grants. When a person becomes owner or admin, Kortix deletes their direct project grants because the account role already covers every project.
- Only an owner touches owners. An admin who tries to remove an owner gets
403. Only an owner can grant theownerrole or change an owner’s role. - The last owner stays. Removing, demoting or leaving as the last owner returns
409. Make another member owner first. - An account role belongs to a person. Binding
owner,adminormemberto a group returns400. Give a group a project role or a custom role instead.
Opening another person’s private session is a separate, owner-controlled setting. See Who can open a session.
Who sees the member list
Owners and admins see every member and every group. A member sees nobody else:
- Members lists only themselves, not even the owners.
kortix membersdoes the same. - They see no group, not even their own. Groups is hidden,
kortix groupslists none, and reading any group answers404. - A project’s access list shows only themselves. A
memberwho manages that project also sees the people and groups with access to it, so they can manage them, and still nobody without access. - The Files share dialog names only themselves.
- Session costs list only their own sessions. Asking for another person’s costs answers
403, and another person’s session answers404. - In a project they do not manage, branches, change requests, the review inbox, gateway logs and spend show only their own work and the sessions they may open. Another member’s private session leaves no trace there.
- SSO group mappings list none.
- Usage by project lists only the projects they can read.
- API keys (
GET /v1/accounts/tokens) list only their own keys and their sessions’ tokens. Only a caller withtoken.revokelists every key in the account. - Service accounts and OAuth clients answer
403: reading them needstoken.create, the same leaf that creates them.
Another member’s access details (View access, GET .../iam/members/:userId/...) and the MFA enforcement preview stay with owners and admins. People you work with in a shared session or project still appear where their work does: as the author of a message, the owner of a session, or a person a secret is shared with.
To show the whole directory to more people, create a custom account role with member.read (every member) and group.read (every group), and assign it to those people or to a group. See Custom roles.
Members and invites
Invite people
- Open Account settings → Members and select Invite.
- Type one or more email addresses.
- Pick the account role: Admin or Member.
- For a member, optionally add projects and a project role for each.
What happens next depends on the address:
- The address has a Kortix login. Kortix adds the person at once, with the project roles you picked.
- The address has no login. Kortix emails an invite link. The invite is valid for 14 days. The project roles apply when the person accepts.
A self-hosted instance with no email provider confirms sign-ups without an email, so a password login does not prove its address there. Kortix adds such a login at once only when it is already a member of the account. Otherwise it creates an invite, and the login with that address accepts it from the project chooser or the Switch Project menu. That login is whoever signed up first with the address. See Unconfirmed email addresses.
Project roles in an invite apply to member invites only. Kortix ignores them on an admin invite, because an admin already reaches every project. To make someone owner, invite them as admin or member, then change their role.
Accept an invite
The invitee opens the link in the email and signs in or signs up with the invited address. Then they select accept or decline. Accept opens the first project the invite grants, or the account they joined.
| Response | Meaning |
|---|---|
403 |
The signed-in address is not the invited address. |
410 |
The invite expired, or it was already used. Ask for a new one. |
409 |
Another login already accepted this invite. |
403 sso_email_domain_unverified |
The invitee signed in through an SSO provider that has not verified their email’s domain. Sign in with the email address instead. |
In the mobile app, the project switcher lists pending invites under Invites. With no project to reopen, the app opens a pending invite first.
Manage invites and members
- Pending invites show on Members. Resending one sends the email again and starts a new 14-day window. Cancelling one revokes the link.
- Edit access in a member’s row menu changes their account role. To change several members at once, select their rows and select Change role.
- Remove from account removes the person’s role, project grants and group memberships. It revokes their personal access keys and the tokens of their running sessions at once. See When a person leaves.
When a person leaves
Removal, Leave and SCIM deactivation (active: false or DELETE, see SCIM provisioning) end the same things in the account, at once:
- the person’s roles, project grants and group memberships;
- their personal access keys and the tokens of their running sessions;
- their notifications and follows in the account’s projects;
- every computer account in the account that reaches a machine they own. This covers a computer they shared with a project and a computer they paired for themselves. The account becomes
revoked, withmetadata.revokedReason: owner_left. The computer stays theirs and keeps working in their other Kortix accounts; - every reminder they set in the account’s projects. The reminder becomes
paused. A reminder that a session’s agent set keeps firing; - their seat on a per-seat plan. Their personal drive folders pass to an owner.
The audit log records one member.offboarded event, titled Offboarded a member, per departure. Its metadata holds reason (removed, left or deprovisioned), computers_revoked and reminders_disabled. A count is 0 when the person had nothing of that kind, and null when that step failed.
Errors
| Code | Status | Cause |
|---|---|---|
account_identity_ambiguous |
409 |
More than one identity in the account uses the email address. |
| — | 409 |
The person is already a member. |
Members are unlimited and cost nothing extra. The account shares one credit wallet. See Plan changes.
Members from the CLI
kortix members ls
kortix members invite alice@example.com --role member --project <project_id>:manager
kortix members set-role alice@example.com --role admin
kortix members rm alice@example.com
kortix members invites ls
kortix members invites resend <invite_id>
kortix members invites cancel <invite_id>
--project <project_id>:<role> repeats, one per project. invite accepts admin or member. set-role accepts owner, admin or member.
Project access
A project has two roles.
| Role | Can do |
|---|---|
manager |
Every project permission: edit the project and its agents, skills, connectors, secrets, models, triggers and Apps; push and merge; act on reviews; manage access; issue project credentials; delete the project. |
member |
Read and run: open the project, see its agents, commands, Apps, members, triggers, reviews and git history; start, follow and stop sessions; fire triggers; submit work for review; read gateway logs and spend. |
A member cannot:
- edit the project, its settings or its sandbox, or delete it;
- read or change secrets, connectors, skills, models or workspace files;
- push or merge code, act on a change request, or delete a git ref;
- create, edit or delete triggers;
- manage access, gateway keys or budgets, or read usage;
- create, edit or deploy Apps;
- bind a session to a channel, or issue a project credential.
The API rejects editor with 400. It reads viewer and user as member. The exact permissions of each role are in Permissions.
Grant project access
- Open Account settings → Projects and pick the project.
- Select Grant access.
- In Grant to, pick people or groups, or type an email to invite someone new.
- Pick the Role.
- Set Agents: All agents or Only these….
- Optionally set Expires. The grant ends at that time.
Inviting an email address outside the account creates an account invite with the member role and this project role. A person who already has a login joins the account as member at once.
Access requests
A signed-in person who opens a project they cannot read sees Request access, with an optional note to the managers. Kortix notifies the project’s managers. One person can send 10 requests per hour, and one project receives at most 30 per hour.
A manager approves the request with a role (member by default) or rejects it. Approving grants the role at once.
Project access from the CLI
kortix access ls # members and their project roles
kortix access invite bob@example.com --role member
kortix access grant <user_id> --role manager # set a member's project role
kortix access revoke <user_id> # remove their project access
kortix access pending # pending project invites
kortix access resend <invite_id> # resend, new 14-day window
kortix access cancel <invite_id>
kortix access requests ls
kortix access requests approve <request_id> --role member
kortix access requests reject <request_id>
These commands act on the linked project, or on --project <project_id>. ls needs project.members.read. Every other command needs project.members.manage. invite and grant take --expires <iso>.
Groups
A group is a named set of people. Grant a role to a group, and every member of the group holds it. A group adds access. It never removes access a person already holds.
- Entitlement. Creating a group, renaming it and adding members need the Enterprise
rbacentitlement. Without it the API returns402entitlement_required. Reading groups, removing members and deleting a group stay open, so an account can clean up after a plan change. Any other edit to a group, including its description, needs the entitlement. - Delete. Deleting a group removes every grant it carried.
- Names. A group name is unique in the account. A duplicate returns
409. - IdP-owned groups. A group that SCIM provisioned belongs to the identity provider. Renaming it or changing its members returns
409group_idp_managed: change it in the IdP. Description edits and deletion stay allowed. See SCIM provisioning.
Give a group a project in Account settings → Projects → Grant access, or from the CLI:
kortix groups create Engineering --description "Everyone who ships code"
kortix groups add Engineering alice@example.com bob@example.com
kortix access grant --group <group_id> --role member --project <project_id>
kortix groups projects Engineering # which projects it reaches, at which role
kortix groups members Engineering
kortix groups remove Engineering bob@example.com
kortix groups rm Engineering
Grant access to one object
Kortix has one grant record: an assignment. Every grant on this page is an assignment.
| Field | Meaning |
|---|---|
| Principal | Who holds it: user, group, service_account (an agent’s identity or a machine key), pending (an invited email), or project (everyone in the project). |
| Role | A built-in or custom role. |
| Scope | account (every project) or project (one project). |
| Object | Optional. One agent, connection (a shared connector account), secret value or Files folder inside the project. |
expires_at |
Optional. The assignment stops granting at that time. The row stays for the audit trail. |
An object assignment carries no permission of its own. It narrows which objects a person reaches with the permissions their role gives. An agent, connector-account or secret grant uses the marker role agent-user. A Files folder grant uses folder-reader, folder-writer or folder-manager.
Agents
Agents are closed by default. A member reaches an agent only when a grant names them, one of their groups, or everyone in the project. A manager reaches every agent until the first grant names that agent. After the first grant, only the named principals reach it, managers included. Account owners and admins reach every agent.
Giving a person an agent also lets them use the secrets and connectors the agent declares. They use them through the agent; they cannot edit them.
Connector accounts and secret values
A shared connector account and a secret value are open to everyone in the project until their first grant. After the first grant, only the named people, groups and agents can use it. Removing the last grant opens it to the project again. Only a person can change these grants; an agent session gets 403.
- Connector accounts: Share accounts and give agents access.
- Secrets: Who can use it.
Everyone in the project
Pick Everyone in followed by the project name to give an agent or a connector account to every project member at once. This principal (project) holds object grants only, never a role. Each person keeps their own project role.
Object grants from the CLI
kortix access grant is the one command for object grants:
kortix access grant --user alice@example.com --agent support-bot
kortix access grant --group <group_id> --agent support-bot --expires 2026-12-31T00:00:00Z
kortix access grant --everyone --agent support-bot
kortix access grant --group <group_id> --connection <connection_id>
kortix access assignments # assignments on the linked project
kortix access assignments --all # every assignment in the account
kortix access revoke <assignment_id>
kortix grants assign <agent> --to <email> writes the same agent grant.
The API route is POST /v1/accounts/:accountId/iam/assignments. The permission it needs follows what you grant:
| Grant | Needs |
|---|---|
| Project role, or an agent grant | project.members.manage on that project |
| Connector account grant | project.connector.connections.manage |
| Secret grant | project.secret.write |
| Account role | member.update, plus owner rights for owner |
| Custom role | policy.create and the rbac entitlement |
Check why someone has access
- In the web app: open the member’s menu on Members and select View access. Without
member.read, it opens only on your own row. - Over the API:
GET /v1/accounts/:accountId/iam/members/:userId/effective?action=project.secret.write&resourceType=project&resourceId=<project_id>returnsallowedand areason, such asproject_role_insufficientorresource_scope_insufficient.POST .../effective:batchchecks up to 64 actions in one call. Asking about yourself answers with your real credential; asking about someone else answers from their roles.
Per-feature access settings
Some features carry their own setting for one resource. Each narrows access. None grants a permission the role denies.
| Setting | Decides |
|---|---|
| App access | Who can open one deployed App |
| Trigger session access | Who can open the sessions one trigger creates |
| Channel rules | Who can start a session from a Slack channel |
| Computer access | Which calls a connected computer accepts |
Agents have their own ceiling
A session runs with the agent’s permissions, not the permissions of the person who started it. Two limits apply: the role bound to the agent’s service account, and the agent’s kortix_permissions in kortix.yaml. Neither widens the other. See What an agent may do.
Custom roles
A custom role is a role your account defines from catalog permissions. It needs the Enterprise rbac entitlement: creating, editing or assigning one without it returns 402 entitlement_required.
- Only adds. A custom role grants permissions. Kortix has no deny rule.
- One scope. A role is account-scoped or project-scoped. It holds only permissions of its scope.
- No escalation. A custom role cannot hold a permission marked no under “Custom role” in Permissions. Owner and admin powers stay with the built-in roles.
- Key and name. The key is 2 to 64 characters of
a-z,0-9and_. It never changes. The name is up to 128 characters. - Delete. Deleting a custom role revokes every assignment of it.
- Built-in roles are fixed. Editing or deleting one returns
400.
Create and edit roles in Account settings → Roles, or from the CLI:
kortix roles create support_lead --name "Support lead" --scope project \
--actions project.read,project.session.start,project.trigger.fire,project.members.manage
kortix roles set-actions support_lead --actions project.read,project.session.start
kortix roles edit support_lead --name "Support leads"
kortix roles show support_lead # permissions and usage
kortix access grant --group <group_id> --role support_lead --project <project_id>
kortix roles rm support_lead
Built-in roles
| Key | Scope | Grants |
|---|---|---|
owner |
account | Full account control |
admin |
account | Members, groups, roles and keys |
member |
account | Baseline membership |
manager |
project | Full project control, including members and delete |
member |
project | Read, run sessions, fire triggers |
agent-user |
project | Nothing. The marker role of an object grant. |
folder-reader, folder-writer, folder-manager |
project | Read, write, or manage one shared Files folder |
kortix roles ls lists them with your custom roles. The folder roles are not in that list: a folder’s share dialog in Files sets them.
IAM as code
kortix roles export writes your custom roles and their bindings to TOML, or to JSON with --format json. kortix roles import <file> creates the roles that are missing, then imports the bindings. Bindings name roles by key, so a file moves between accounts.
kortix roles export --out roles.toml
kortix roles import roles.toml
kortix roles assign, unassign and assignments, and the /iam/policies routes, are a legacy API over the same assignments. They cover custom roles only. Use kortix access grant and /iam/assignments.
Super-admin
Super-admin is a flag on one membership, not a role. A super-admin passes every permission check in the account. Each request a super-admin makes is in the audit log like any other request.
- The person who creates an account starts as owner and super-admin.
- Only an owner grants or revokes it:
kortix members super-admin <user> on|off, orPATCH /v1/accounts/:accountId/iam/members/:userId/super-admin. - Demoting an owner clears their super-admin flag and records
iam.member.super_admin.revoke. - A super-admin is exempt from the account’s MFA requirement. SSO enforcement still applies. See Sign-in, SSO & API keys.
Branding
An account with the Enterprise branding entitlement replaces the Kortix marks its members see in the web app. Open Account settings → Branding.
| Item | Where it shows |
|---|---|
logo |
The wide brandmark in the app |
icon |
The square mark |
favicon |
The browser-tab icon |
logo_dark, icon_dark, favicon_dark |
The same, in dark mode |
app_name |
Replaces “Kortix” in the browser tab title. Up to 60 characters. |
- Formats. PNG, JPEG, WebP, SVG or ICO, up to 1 MiB each. Kortix rejects an SVG that carries script or other active content.
- Fallbacks. A missing logo uses the icon. A missing favicon uses the icon. A missing dark variant uses the dark icon, then the light image.
- Scope. Inside a project, members see the brand of the account that owns the project. The favicon follows the operating system’s color scheme; the other marks follow the app theme.
- Kortix stays. Sign-in pages, emails and public share pages stay Kortix-branded.
- Plan change. When the entitlement lapses, members see Kortix again. Nothing is deleted. Removing images and resetting stay available without the entitlement.
Writes need account.write and the entitlement (402 entitlement_required otherwise).
Audit log
The audit log records who did what in the account, when, through which credential, and whether it was allowed. Recording is always on. Reading, exporting and streaming the log need the Enterprise auditAccess entitlement.
What is recorded
Kortix writes one row for every request that reaches the API: HTTP requests, WebSocket upgrades, preview requests, git clones and pushes, and SCIM calls. A refused request is a row with outcome: denied. Events outside a request, such as a sandbox reading a secret or a background job expiring a grant, are rows too.
| Field | Values |
|---|---|
action |
domain.resource.verb, for example iam.group.create. One per route. |
actor_type |
human, agent, service_account, system, anonymous |
credential_kind |
browser_session, personal_access_token, oauth_app, session_token, api_key, service_account, scim_token. The web app shows it as Via. |
credential_id |
The id of the key or session. Never the secret. |
outcome |
success, failure, denied, pending |
metadata.http |
The route template, never the raw path. |
An agent’s row also names the person the agent acted for (on_behalf_of_user_id). Kortix derives the caller and the credential from what it authenticated, never from a request header. An anonymous request that names one of your projects is written with actor_type: anonymous.
Kortix does not record health probes, CORS preflights, or anonymous visitors to a deployed App.
Read the log
Open Account settings → Audit log. Reading needs audit.read (owners and admins) and the entitlement.
The Session filter searches the selected project’s sessions that you can open, by name or session-id prefix, on the server. It lists 20 matches at a time: Load more reads the next 20. To filter by any other session, paste its full session id into the search field and pick it. A pasted id works with no project selected, for a session you cannot open, and for a deleted session.
kortix audit ls --since 24h
kortix audit ls --outcome denied --since 7d
kortix audit ls --action iam. --json
kortix audit ls --credential-kind oauth_app --all
kortix audit project <project_id>
kortix audit session <session_id> --project <project_id>
| Flag | Filters on |
|---|---|
--since, --until |
Time. ISO-8601, or a span such as 30m, 24h, 7d, 2w. |
--action <prefix> |
An action prefix, such as iam. or session. |
--actor <user_id>, --actor-type <t> |
Who acted |
--credential-kind <k> |
What the API authenticated |
--outcome <o> |
success, failure, denied, pending |
--project, --session |
One project or session |
--source, --phase, --resource-type |
Execution source, lifecycle phase, resource type |
--request-id, --correlation-id |
One request, or one chain of events |
-q <text> |
Free text over action, resource, project and session |
--limit, --cursor, --all |
Paging: 50 per page by default, 200 at most; --all follows every cursor |
The API route is GET /v1/accounts/:accountId/audit with the same filters as query parameters (actor_type, credential_kind, and so on).
- Project log:
GET /v1/projects/:projectId/auditneedsproject.members.manageand the entitlement. - Session timeline:
GET /v1/projects/:projectId/sessions/:sessionId/auditneedsproject.session.read. Without the entitlement it returns only the unresolved pending approvals.
Who was active, and how often
The audit log names an identity, not a person. A sandbox, the CLI, or a script that holds a person’s token writes rows as that person, and those rows can outnumber the rows of what the person did in a browser by 100 to 1 or more. To ask “who used this project, and on which days”, read the activity rollup instead of counting log rows.
kortix audit activity --project <project_id> --since 6w
kortix audit activity --project <project_id> --since 6w --client browser
kortix audit activity --actor <user_id> --since 2026-09-01 --until 2026-09-30 --json
Each user gets one line: the days with activity, the distinct UTC hours with activity, the number of events, the last day, and one character per day (taller means more active hours).
| Flag | Filters on |
|---|---|
--since, --until |
UTC days, inclusive. A date, an ISO-8601 instant, or a span such as 6w. Default: the last 28 days. At most 400 days. |
--client <c> |
browser: a person in a web page (a Mozilla/ user agent). program: the CLI, the SDK, a sandbox, or a script acting as the user. |
--project, --actor, --actor-type, --credential-kind |
As for kortix audit ls |
The API route is GET /v1/accounts/:accountId/audit/activity, with since, until, project_id, actor, client, actor_type and credential_kind. It needs the same audit.read permission and entitlement as the log. A background job adds each closed 15-minute window of the log to the rollup about 2 hours after it closes. rolled_through in the response is the instant the counts reach. The rollup covers the last 90 days of the log.
Retention and export
| Age of an event | Where it lives | How to read it |
|---|---|---|
| 0 to 90 days | The database | The web app, kortix audit ls, the API, webhooks, export |
| 90 to 365 days | A locked archive that nobody can shorten or delete | Export only |
| More than 365 days | Deleted | Not available |
kortix audit export --since 180d --format jsonl --out audit.jsonl
kortix audit export --action iam. --format csv --out iam.csv
Export takes the same filters, returns events oldest first, and reads the archive and the database as one list. Over the API: GET /v1/accounts/:accountId/audit/export?format=csv|jsonl, 10,000 events per page. Follow the X-Audit-Next-Cursor header until X-Audit-Complete is true.
Stream to a SIEM
An audit webhook POSTs every new event to your endpoint. Managing webhooks needs account.write. Creating, enabling or disabling one also needs the entitlement. Deleting one never does.
kortix audit webhooks add --name siem --url https://siem.example.com/kortix --action-prefix iam.
kortix audit webhooks ls
kortix audit webhooks disable <webhook_id>
kortix audit webhooks enable <webhook_id>
kortix audit webhooks rm <webhook_id>
add prints the signing secret (whsec_…) once, and sends a test event at once. --action-prefix limits delivery to matching actions. The URL must be http or https and must not resolve to a private address.
Each delivery is a POST with the body {"schema_version": 1, "event": {…}} and these headers:
| Header | Value |
|---|---|
X-Kortix-Signature |
sha256= and the hex HMAC-SHA256 of the raw body, keyed with the signing secret |
X-Kortix-Idempotency-Key |
A stable key per webhook and event. Use it to drop duplicates. |
X-Kortix-Webhook-Id |
The webhook |
X-Kortix-Event |
audit |
Verify a delivery before you trust it:
import { createHmac, timingSafeEqual } from 'node:crypto';
function verify(rawBody: string, header: string, secret: string): boolean {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex');
return header.length === expected.length && timingSafeEqual(Buffer.from(header), Buffer.from(expected));
}
A 2xx response within 5 seconds is a success. Kortix retries any other result up to 8 attempts, waiting 30 seconds and doubling up to 1 hour between attempts. After the last attempt the delivery is dead_letter. Read deliveries with GET /v1/accounts/:accountId/audit/webhooks/:webhookId/deliveries?status=<status>, and send one again with POST .../deliveries/:deliveryId/replay.
Action names
Every action is domain.resource.verb, and each API route has exactly one. Filter by prefix: iam. for access changes, git. for clones and pushes (git.clone, git.push; a push lists its refs in metadata.refs). A request that matched no route is api.route.unmatched. Audit actions lists every action and its title.
Permissions
A permission is one action, such as project.secret.write. Roles are sets of permissions. Read the live catalog with kortix permissions ls, filter with --scope account|project or --area <area>, and open one with kortix permissions show <action>. Over the API: GET /v1/accounts/:accountId/iam/permissions, which also returns each permission’s implies list.
Level is view, edit or admin.
Account permissions
| Action | Area | Level | Custom role | Meaning |
|---|---|---|---|---|
account.read |
account | view | yes | View the account: its name, members and settings. |
account.write |
account | edit | yes | Rename the account and change its settings, including the MFA requirement. |
account.delete |
account | edit | no | Permanently delete the account and everything in it. |
audit.read |
audit | view | yes | Read the audit log. |
billing.read |
billing | view | yes | View the plan, credit balance, invoices and usage. |
billing.write |
billing | edit | no | Change the plan, payment method and spending limits. |
group.read |
groups | view | yes | View groups and who belongs to them. |
group.create |
groups | edit | no | Create a group. |
group.update |
groups | edit | no | Rename a group or change its description. |
group.delete |
groups | edit | no | Delete a group, removing every grant it carried. |
group.members.manage |
groups | edit | no | Add people to a group and remove them. |
member.read |
members | view | yes | View the member directory. |
member.invite |
members | edit | no | Invite people to the account. |
member.update |
members | edit | no | Change a member’s account role. |
member.remove |
members | edit | no | Remove a member and revoke their tokens. |
member.super_admin.grant |
members | admin | no | Grant or revoke super-admin. |
project.create |
projects | edit | yes | Create a project in this account. |
role.read |
roles | view | yes | View roles and the permissions they carry. |
role.create |
roles | edit | no | Create a custom role. |
role.update |
roles | edit | no | Rename a custom role or change its permissions. |
role.delete |
roles | edit | no | Delete a custom role, revoking every assignment of it. |
policy.read |
roles | view | yes | View which principals hold which roles. |
policy.create |
roles | edit | no | Assign a role to a person, group or agent identity. |
policy.delete |
roles | edit | no | Revoke a role assignment. |
token.read |
tokens | view | yes | List your own personal access keys. With token.revoke, the list holds every key in the account. |
token.create |
tokens | edit | no | Mint account keys: service-account keys and OAuth apps. |
token.revoke |
tokens | edit | no | Revoke account keys and other people’s personal access keys. |
token.personal.create |
tokens | edit | yes | Mint a personal access key that acts as you, for example for kortix login. |
token.personal.revoke |
tokens | edit | yes | Revoke a personal access key you minted. |
Project permissions
Every project permission can go in a custom role.
| Action | Area | Level | Meaning |
|---|---|---|---|
project.read |
project | view | Open the project and see its workspace. |
project.write |
project | edit | Change the project: its settings, configuration and contents. |
project.delete |
project | edit | Archive or permanently delete the project. |
project.settings.write |
project | edit | Change name, description, icon, sandbox provider, feature flags and the connected repository. |
project.sandbox.write |
project | edit | Manage sandbox templates and snapshot rebuilds. |
project.session.read |
sessions | view | View sessions and their transcripts. |
project.session.start |
sessions | edit | Start a session and send prompts to an agent. |
project.session.stop |
sessions | edit | Stop a running session. |
project.session.bindings.write |
sessions | edit | Bind a session to a channel, such as a Slack thread. |
project.members.read |
members | view | View who has access to this project. |
project.members.manage |
members | edit | Grant and revoke access to this project, including agent grants. |
project.agent.read |
customize | view | View the project’s agents. |
project.agent.write |
customize | edit | Add, edit and remove agents. |
project.skill.read |
customize | view | View the project’s skills. |
project.skill.write |
customize | edit | Add, edit and remove skills. |
project.command.read |
customize | view | View the project’s slash commands. |
project.command.write |
customize | edit | Shows Edit on a slash command, which opens a session that changes it. The command file itself changes through a git push, so the write needs project.gitops.push. |
project.connector.read |
customize | view | View the project’s connectors. |
project.connector.write |
customize | edit | Add, edit and remove connectors. |
project.connector.connections.manage |
customize | edit | Manage everyone’s connector accounts, not only your own. |
project.secret.read |
customize | view | See which secrets exist and where they are used. Never their values. |
project.secret.write |
customize | edit | Set and remove secret values. |
project.model.read |
customize | view | See allowed models, default models and gateway routing. |
project.model.write |
customize | edit | Change allowed models, default models and gateway routing. |
project.file.read |
files | view | Read files in the project workspace. |
project.file.write |
files | edit | Create, edit and delete files in the project workspace. |
project.gitops.read |
git | view | View the repository, its branches and its history. |
project.gitops.push |
git | edit | Push commits to the project repository. |
project.gitops.merge |
git | edit | Merge a change request into the default branch. |
project.gitops.ref.any |
git | edit | Push git refs beyond your own session branch. |
project.gitops.ref.delete |
git | edit | Delete a git ref. |
project.review.read |
git | view | View change requests and their diffs. |
project.review.submit |
git | edit | Open a change request for review. |
project.review.act |
git | edit | Approve, request changes on, or close a change request. |
project.trigger.read |
triggers | view | View triggers and when they last fired. |
project.trigger.create |
triggers | edit | Create a trigger. |
project.trigger.update |
triggers | edit | Change a trigger’s schedule, prompt or agent. |
project.trigger.delete |
triggers | edit | Delete a trigger. |
project.trigger.fire |
triggers | edit | Fire a trigger by hand. |
project.gateway.logs.read |
spend | view | Read the LLM gateway request log, including prompts and responses. |
project.gateway.spend.read |
spend | view | View model spend for this project. |
project.gateway.budget.set |
spend | edit | Set the project’s model-spend budget. |
project.gateway.keys.manage |
spend | edit | Create, list and revoke the project’s LLM gateway keys (kortix_gw_). |
project.usage.read |
spend | view | View usage and costs for this project. |
project.app.read |
apps | view | View the project’s Apps. |
project.app.write |
apps | edit | Create, edit and remove Apps. Read and set an App’s access policy. |
project.app.deploy |
apps | edit | Deploy an App and manage its live version. Read its deployments, deployment events, runtime logs, machines, volumes and snapshots. |
project.app.admin |
apps | edit | Run commands in an App, restore and destroy its volumes, delete an App that has volumes, and reach its admin-only services. |
project.credentials.issue |
tokens | admin | List, mint or revoke a project credential: a CLI token or a git token. |
project.credentials.issue is human-only. No role or grant gives it to an agent.
Leave or delete an account
Leave
Open Account settings → Members, open the menu on your own row, and select Leave account. You lose access to the account and its projects. Your computers stop serving the account, and your reminders in its projects pause. See When a person leaves. The last owner cannot leave (409): make another member owner first.
Delete
Deletion needs account.delete, which only an owner holds. It acts on your primary account: the first account you joined, normally the personal account Kortix created at sign-up. Open Settings → Profile and select Delete account. Pick one:
- Grace period. Kortix deletes the account 14 days later. You can cancel any time before then.
- Delete immediately. Kortix deletes the account at once. This cannot be undone.
Deletion removes:
- the account’s sandboxes, session files and Kortix-managed repositories;
- every project and session in the account, with its secrets and connector accounts;
- the subscription, which Kortix cancels, and the remaining credits;
- for your personal account, your login, your devices and your notifications.
The deletion routes are under /v1/account/ in the API reference.
To leave a team account you do not own, use Leave instead.