## Stack Part of [CODAGT-1341](https://linear.app/codercom/issue/CODAGT-1341/support-organization-level-skills-in-coder-agents). This stack adds organization skills to Coder Agents: admins publish a skill once per organization, share it with groups or members, and chats in that organization load it next to personal and workspace skills. It replaces the 21-PR draft stack #30584 to #30604 with five PRs, bottom to top: 1. **#30609** data model: one migration, queries, RBAC and dbauthz (this PR) 2. #30610 organization skill API routes and the scope-neutral SDK 3. #30611 sharing ACL routes 4. #30612 settings UI: shared skills table, admin page, member section 5. #30613 chats: chatd loading, `/` menu, docs ## What changes This PR adds the data model and authorization for organization skills. Personal skills keep working unchanged: `git diff origin/main -- codersdk site` shows only generated RBAC and API key scope additions (`apikey_scopes_gen.go`, `rbacresources_gen.go`, `rbacresourcesGenerated.ts`, the RBAC and scope unions in `typesGenerated.ts`) and `codersdk.ResourceTypeOrganizationSkill` with its friendly string. No personal route, SDK type or site component changes, and `coderd/userskills_test.go` changes only by mechanical constant renames. **One migration, `000621_skills`** (please review it closely): - renames `user_skills` to `skills` with its constraints, index and triggers, and recreates the cap function and `delete_deleted_user_resources`, whose PL/pgSQL bodies name the table; - adds `organization_id` and `project_id` (`ON DELETE CASCADE`), `enabled` (default true), and `group_acl` / `user_acl` (`jsonb`, default `{}`), with CHECKs for exactly one owner, ACLs that are JSON objects, and ACLs that stay empty unless an organization owns the row, plus partial unique name indexes per owner kind; - replaces the cap trigger with `enforce_skills_per_owner_limit()`: 100 rows per owner, disabled rows included, locking the owner row `FOR NO KEY UPDATE` so unrelated foreign key checks are not blocked; - adds a `BEFORE DELETE` trigger on `organization_members` that removes a departing member from `user_acl` on that organization's skills, so rejoining doesn't restore a direct grant; - adds the `organization_skill` `resource_type` and `api_key_scope` enum values last; nothing in the migration uses them. The down migration undoes the three old migrations in reverse order: it drops organization and project rows and restores `user_skills`, its names, the cap function and `user_id NOT NULL`. Authorization: a new RBAC resource `organization_skill` (create, read, update, delete, share). Owner and org admin get it; site and org auditors get read; members read only through the skill's ACL, which applies only to members of its organization. `Skill.RBACObject()` returns the organization object with both ACLs; project rows stay denied to everyone. New sqlc queries cover organization insert, get, list (SQL-filtered through `GetAuthorizedOrganizationSkillMetadata` and a `regosql` converter), update and delete, with dbauthz wrappers and the audit table entries. No routes yet. ## Commits The first commit reproduces the reviewed code from the old stack; each later commit is a labeled trim or fix. - `baa3150e3b7` feat: add the organization skills data model. Reproduction: every non-site file this commit changes equals the reviewed old `authz` head `1e16b3004c4`, except that the old stack's migrations 000615, 000616 and 000617 are merged into one migration (then `000615_skills`, now `000621_skills`) with one fixture (`testdata/fixtures/000621_skills.up.sql`) and one migration test (now `testMigration000621Skills`). At that commit, `dump.sql` was byte-identical to the old head's. - `1b84e83463a` test(coderd/database): keep only the SQL paths of the org skill matrix. `TestOrganizationSkillAuthorization` becomes `TestOrganizationSkillQueries` instead of being deleted, because coverage showed it is this PR's only run of the `GetAuthorizedOrganizationSkillMetadata` row scan (80% to 65% without it) and of the organization update and delete queries (100% to 0%). Swapping `group_acl` and `user_acl` in the converter makes `GrantedMember` fail. The removed cases are decided by `TestRolePermissions`, `TestSkillRBACObjectOrganizationACL` and the dbauthz method suite. - `e2931b412e9` test(coderd/database): fold the skill cap cases into existing coverage. The user case is covered by `TestUserSkillLimit` and `TestUserSkillLimitConcurrentCreates`; the organization case folds into `ConcurrentOrganizationInsertsHonorCap`, which now also checks that disabled rows count and another organization is unaffected (mutation checked); the project case stays. - `be62aea9021` test(coderd/rbac): drop `TestOrganizationSkillReadScope`, covered by `TestExternalScopeNames` and the generated scope file. - `0c275ba37de` merges main at `454a2fcc697`, which took 000615 to 000618: it renumbers the migration to 000619 and resolves `dump.sql`, `check_constraint.go` and the generated API docs. `8f2b4b87ee2` merges main at `ad85646164e`, which took 000619: it renumbers the migration to 000620. - `5248d56b64f` merges main at `e7b76872098`, which took 000620 (`000620_audit_chat_project_instructions_resource_type`): it renumbers the migration, fixture and migration test to `000621_skills` (step `Migration000621Skills`, version 621), and resolves `enterprise/audit/table.go` (keeping main's `AuditableChatProjectInstructions` entries and the `Skill` entry), `dump.sql` and `models.go` (the `resource_type` enum gets `chat_project_instructions`, then `organization_skill`) and the regenerated `schemas.md`. The up and down SQL are unchanged by every renumbering. ## Size Production +549/-67, tests +728/-33, generated +881/-314; total +2158/-414. This is above the 500-line reviewer-friendly limit on purpose: Mike asked for 4 to 5 PRs instead of the 21 small ones this stack replaces. ## Replaces #30584 (rename `user_skills` to `skills`), #30585 (skill owners), #30586 (organization skill authorization). ## Validation - Migration test: up keeps the existing personal row and its ID; down restores the `user_skills` names, cap function and `NOT NULL`, and drops organization rows; soft-deleting a user removes their skills after up, after down, and after re-up. - `go test` passed on `be62aea9021`, before the main merges, for `coderd` (skill tests), `coderd/database`, `dbauthz`, `migrations`, `gentest`, `coderd/rbac/...`, `coderd/x/chatd`, `coderd/x/skills`, `enterprise/audit` and `enterprise/coderd`; `make lint/check-scopes` passed; the four personal skills Vitest files pass unchanged. - On `5248d56b64f`: build, vet, `TestMigrate`, `TestMigrationChain`, the `migrations`, `database`, `dbauthz`, `gentest`, `rbac` and `enterprise/audit` packages pass; `make gen` run twice is clean, and `make pre-commit` passes. - Remote UAT round 7 through Coder Agents passed on the whole stack; see #30613's Validation for scope and findings. > Xum opened this PR on behalf of @ibetitsmike.
68 KiB
Generated
title
| title |
|---|
| Members |
List organization members
Code samples
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
GET /api/v2/organizations/{organization}/members
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string | true | Organization ID |
Example responses
200 Response
[
{
"avatar_url": "string",
"created_at": "2019-08-24T14:15:22Z",
"email": "string",
"global_roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"has_ai_seat": true,
"is_service_account": true,
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"status": "active",
"updated_at": "2019-08-24T14:15:22Z",
"user_created_at": "2019-08-24T14:15:22Z",
"user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
"user_updated_at": "2019-08-24T14:15:22Z",
"username": "string"
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.OrganizationMemberWithUserData |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» avatar_url |
string | false | ||
» created_at |
string(date-time) | false | ||
» email |
string | false | ||
» global_roles |
array | false | ||
»» display_name |
string | false | ||
»» name |
string | false | ||
»» organization_id |
string | false | ||
» has_ai_seat |
boolean | false | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. | |
» is_service_account |
boolean | false | ||
» last_seen_at |
string(date-time) | false | ||
» login_type |
codersdk.LoginType | false | ||
» name |
string | false | ||
» organization_id |
string(uuid) | false | ||
» roles |
array | false | ||
» status |
codersdk.UserStatus | false | ||
» updated_at |
string(date-time) | false | ||
» user_created_at |
string(date-time) | false | ||
» user_id |
string(uuid) | false | ||
» user_updated_at |
string(date-time) | false | ||
» username |
string | false |
Enumerated Values
| Property | Value(s) |
|---|---|
login_type |
``, github, none, oidc, password, token |
status |
active, suspended |
To perform this operation, you must be authenticated. Learn more.
Get member roles by organization
Code samples
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members/roles \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
GET /api/v2/organizations/{organization}/members/roles
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string(uuid) | true | Organization ID |
Example responses
200 Response
[
{
"assignable": true,
"built_in": true,
"display_name": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.AssignableRoles |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» assignable |
boolean | false | ||
» built_in |
boolean | false | Built in roles are immutable | |
» display_name |
string | false | ||
» name |
string | false | ||
» organization_id |
string(uuid) | false | ||
» organization_member_permissions |
array | false | Organization member permissions are specific for the organization in the field 'OrganizationID' above. | |
»» action |
codersdk.RBACAction | false | ||
»» negate |
boolean | false | Negate makes this a negative permission | |
»» resource_type |
codersdk.RBACResource | false | ||
» organization_permissions |
array | false | Organization permissions are specific for the organization in the field 'OrganizationID' above. | |
» site_permissions |
array | false | ||
» user_permissions |
array | false |
Enumerated Values
| Property | Value(s) |
|---|---|
action |
application_connect, assign, create, create_agent, delete, delete_agent, read, read_personal, share, ssh, start, stop, unassign, update, update_agent, update_personal, use, view_insights |
resource_type |
*, ai_gateway_key, ai_model_price, ai_provider, ai_seat, aibridge_interception, api_key, assign_org_role, assign_role, audit_log, boundary_log, boundary_usage, chat, chat_model_config, chat_project, chat_project_memory, connection_log, crypto_key, debug_info, deployment_config, deployment_stats, file, group, group_member, idpsync_settings, inbox_notification, license, mcp_server_config, notification_message, notification_preference, notification_template, oauth2_app, oauth2_app_code_token, oauth2_app_secret, organization, organization_member, organization_skill, prebuilt_workspace, provisioner_daemon, provisioner_jobs, replicas, system, tailnet_coordinator, template, usage_event, user, user_secret, user_skill, webpush_subscription, workspace, workspace_agent_devcontainers, workspace_agent_resource_monitor, workspace_build_orchestration, workspace_dormant, workspace_proxy |
To perform this operation, you must be authenticated. Learn more.
Update a custom organization role
Code samples
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/organizations/{organization}/members/roles \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
PUT /api/v2/organizations/{organization}/members/roles
Body parameter
{
"display_name": "string",
"name": "string",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string(uuid) | true | Organization ID |
body |
body | codersdk.CustomRoleRequest | true | Update role request |
Example responses
200 Response
[
{
"display_name": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.Role |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» display_name |
string | false | ||
» name |
string | false | ||
» organization_id |
string(uuid) | false | ||
» organization_member_permissions |
array | false | Organization member permissions are specific for the organization in the field 'OrganizationID' above. | |
»» action |
codersdk.RBACAction | false | ||
»» negate |
boolean | false | Negate makes this a negative permission | |
»» resource_type |
codersdk.RBACResource | false | ||
» organization_permissions |
array | false | Organization permissions are specific for the organization in the field 'OrganizationID' above. | |
» site_permissions |
array | false | ||
» user_permissions |
array | false |
Enumerated Values
| Property | Value(s) |
|---|---|
action |
application_connect, assign, create, create_agent, delete, delete_agent, read, read_personal, share, ssh, start, stop, unassign, update, update_agent, update_personal, use, view_insights |
resource_type |
*, ai_gateway_key, ai_model_price, ai_provider, ai_seat, aibridge_interception, api_key, assign_org_role, assign_role, audit_log, boundary_log, boundary_usage, chat, chat_model_config, chat_project, chat_project_memory, connection_log, crypto_key, debug_info, deployment_config, deployment_stats, file, group, group_member, idpsync_settings, inbox_notification, license, mcp_server_config, notification_message, notification_preference, notification_template, oauth2_app, oauth2_app_code_token, oauth2_app_secret, organization, organization_member, organization_skill, prebuilt_workspace, provisioner_daemon, provisioner_jobs, replicas, system, tailnet_coordinator, template, usage_event, user, user_secret, user_skill, webpush_subscription, workspace, workspace_agent_devcontainers, workspace_agent_resource_monitor, workspace_build_orchestration, workspace_dormant, workspace_proxy |
To perform this operation, you must be authenticated. Learn more.
Insert a custom organization role
Code samples
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/members/roles \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
POST /api/v2/organizations/{organization}/members/roles
Body parameter
{
"display_name": "string",
"name": "string",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string(uuid) | true | Organization ID |
body |
body | codersdk.CustomRoleRequest | true | Insert role request |
Example responses
200 Response
[
{
"display_name": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.Role |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» display_name |
string | false | ||
» name |
string | false | ||
» organization_id |
string(uuid) | false | ||
» organization_member_permissions |
array | false | Organization member permissions are specific for the organization in the field 'OrganizationID' above. | |
»» action |
codersdk.RBACAction | false | ||
»» negate |
boolean | false | Negate makes this a negative permission | |
»» resource_type |
codersdk.RBACResource | false | ||
» organization_permissions |
array | false | Organization permissions are specific for the organization in the field 'OrganizationID' above. | |
» site_permissions |
array | false | ||
» user_permissions |
array | false |
Enumerated Values
| Property | Value(s) |
|---|---|
action |
application_connect, assign, create, create_agent, delete, delete_agent, read, read_personal, share, ssh, start, stop, unassign, update, update_agent, update_personal, use, view_insights |
resource_type |
*, ai_gateway_key, ai_model_price, ai_provider, ai_seat, aibridge_interception, api_key, assign_org_role, assign_role, audit_log, boundary_log, boundary_usage, chat, chat_model_config, chat_project, chat_project_memory, connection_log, crypto_key, debug_info, deployment_config, deployment_stats, file, group, group_member, idpsync_settings, inbox_notification, license, mcp_server_config, notification_message, notification_preference, notification_template, oauth2_app, oauth2_app_code_token, oauth2_app_secret, organization, organization_member, organization_skill, prebuilt_workspace, provisioner_daemon, provisioner_jobs, replicas, system, tailnet_coordinator, template, usage_event, user, user_secret, user_skill, webpush_subscription, workspace, workspace_agent_devcontainers, workspace_agent_resource_monitor, workspace_build_orchestration, workspace_dormant, workspace_proxy |
To perform this operation, you must be authenticated. Learn more.
Delete a custom organization role
Code samples
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/organizations/{organization}/members/roles/{roleName} \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
DELETE /api/v2/organizations/{organization}/members/roles/{roleName}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string(uuid) | true | Organization ID |
roleName |
path | string | true | Role name |
Example responses
200 Response
[
{
"display_name": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.Role |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» display_name |
string | false | ||
» name |
string | false | ||
» organization_id |
string(uuid) | false | ||
» organization_member_permissions |
array | false | Organization member permissions are specific for the organization in the field 'OrganizationID' above. | |
»» action |
codersdk.RBACAction | false | ||
»» negate |
boolean | false | Negate makes this a negative permission | |
»» resource_type |
codersdk.RBACResource | false | ||
» organization_permissions |
array | false | Organization permissions are specific for the organization in the field 'OrganizationID' above. | |
» site_permissions |
array | false | ||
» user_permissions |
array | false |
Enumerated Values
| Property | Value(s) |
|---|---|
action |
application_connect, assign, create, create_agent, delete, delete_agent, read, read_personal, share, ssh, start, stop, unassign, update, update_agent, update_personal, use, view_insights |
resource_type |
*, ai_gateway_key, ai_model_price, ai_provider, ai_seat, aibridge_interception, api_key, assign_org_role, assign_role, audit_log, boundary_log, boundary_usage, chat, chat_model_config, chat_project, chat_project_memory, connection_log, crypto_key, debug_info, deployment_config, deployment_stats, file, group, group_member, idpsync_settings, inbox_notification, license, mcp_server_config, notification_message, notification_preference, notification_template, oauth2_app, oauth2_app_code_token, oauth2_app_secret, organization, organization_member, organization_skill, prebuilt_workspace, provisioner_daemon, provisioner_jobs, replicas, system, tailnet_coordinator, template, usage_event, user, user_secret, user_skill, webpush_subscription, workspace, workspace_agent_devcontainers, workspace_agent_resource_monitor, workspace_build_orchestration, workspace_dormant, workspace_proxy |
To perform this operation, you must be authenticated. Learn more.
Get organization member
Code samples
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members/{user} \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
GET /api/v2/organizations/{organization}/members/{user}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string | true | Organization ID |
user |
path | string | true | User ID, name, or me |
Example responses
200 Response
{
"avatar_url": "string",
"created_at": "2019-08-24T14:15:22Z",
"email": "string",
"global_roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"has_ai_seat": true,
"is_service_account": true,
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"status": "active",
"updated_at": "2019-08-24T14:15:22Z",
"user_created_at": "2019-08-24T14:15:22Z",
"user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
"user_updated_at": "2019-08-24T14:15:22Z",
"username": "string"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | codersdk.OrganizationMemberWithUserData |
To perform this operation, you must be authenticated. Learn more.
Add organization member
Code samples
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/members/{user} \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
POST /api/v2/organizations/{organization}/members/{user}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string | true | Organization ID |
user |
path | string | true | User ID, name, or me |
Example responses
200 Response
{
"created_at": "2019-08-24T14:15:22Z",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"updated_at": "2019-08-24T14:15:22Z",
"user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | codersdk.OrganizationMember |
To perform this operation, you must be authenticated. Learn more.
Remove organization member
Code samples
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/organizations/{organization}/members/{user} \
-H 'Coder-Session-Token: API_KEY'
DELETE /api/v2/organizations/{organization}/members/{user}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string | true | Organization ID |
user |
path | string | true | User ID, name, or me |
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 204 | No Content | No Content |
To perform this operation, you must be authenticated. Learn more.
Assign role to organization member
Code samples
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/organizations/{organization}/members/{user}/roles \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
PUT /api/v2/organizations/{organization}/members/{user}/roles
Body parameter
{
"roles": [
"string"
]
}
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string | true | Organization ID |
user |
path | string | true | User ID, name, or me |
body |
body | codersdk.UpdateRoles | true | Update roles request |
Example responses
200 Response
{
"created_at": "2019-08-24T14:15:22Z",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"updated_at": "2019-08-24T14:15:22Z",
"user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | codersdk.OrganizationMember |
To perform this operation, you must be authenticated. Learn more.
Paginated organization members
Code samples
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/paginated-members \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
GET /api/v2/organizations/{organization}/paginated-members
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
organization |
path | string | true | Organization ID |
q |
query | string | false | Member search query |
after_id |
query | string(uuid) | false | After ID |
limit |
query | integer | false | Page limit, if 0 returns all members |
offset |
query | integer | false | Page offset |
Example responses
200 Response
[
{
"count": 0,
"members": [
{
"avatar_url": "string",
"created_at": "2019-08-24T14:15:22Z",
"email": "string",
"global_roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"has_ai_seat": true,
"is_service_account": true,
"last_seen_at": "2019-08-24T14:15:22Z",
"login_type": "",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"roles": [
{
"display_name": "string",
"name": "string",
"organization_id": "string"
}
],
"status": "active",
"updated_at": "2019-08-24T14:15:22Z",
"user_created_at": "2019-08-24T14:15:22Z",
"user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
"user_updated_at": "2019-08-24T14:15:22Z",
"username": "string"
}
]
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.PaginatedMembersResponse |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» count |
integer | false | ||
» members |
array | false | ||
»» avatar_url |
string | false | ||
»» created_at |
string(date-time) | false | ||
»» email |
string | false | ||
»» global_roles |
array | false | ||
»»» display_name |
string | false | ||
»»» name |
string | false | ||
»»» organization_id |
string | false | ||
»» has_ai_seat |
boolean | false | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. | |
»» is_service_account |
boolean | false | ||
»» last_seen_at |
string(date-time) | false | ||
»» login_type |
codersdk.LoginType | false | ||
»» name |
string | false | ||
»» organization_id |
string(uuid) | false | ||
»» roles |
array | false | ||
»» status |
codersdk.UserStatus | false | ||
»» updated_at |
string(date-time) | false | ||
»» user_created_at |
string(date-time) | false | ||
»» user_id |
string(uuid) | false | ||
»» user_updated_at |
string(date-time) | false | ||
»» username |
string | false |
Enumerated Values
| Property | Value(s) |
|---|---|
login_type |
``, github, none, oidc, password, token |
status |
active, suspended |
To perform this operation, you must be authenticated. Learn more.
Get site member roles
Code samples
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/roles \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
GET /api/v2/users/roles
Example responses
200 Response
[
{
"assignable": true,
"built_in": true,
"display_name": "string",
"name": "string",
"organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
"organization_member_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"organization_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"site_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
],
"user_permissions": [
{
"action": "application_connect",
"negate": true,
"resource_type": "*"
}
]
}
]
Responses
| Status | Meaning | Description | Schema |
|---|---|---|---|
| 200 | OK | OK | array of codersdk.AssignableRoles |
Response Schema
Status Code 200
| Name | Type | Required | Restrictions | Description |
|---|---|---|---|---|
[array item] |
array | false | ||
» assignable |
boolean | false | ||
» built_in |
boolean | false | Built in roles are immutable | |
» display_name |
string | false | ||
» name |
string | false | ||
» organization_id |
string(uuid) | false | ||
» organization_member_permissions |
array | false | Organization member permissions are specific for the organization in the field 'OrganizationID' above. | |
»» action |
codersdk.RBACAction | false | ||
»» negate |
boolean | false | Negate makes this a negative permission | |
»» resource_type |
codersdk.RBACResource | false | ||
» organization_permissions |
array | false | Organization permissions are specific for the organization in the field 'OrganizationID' above. | |
» site_permissions |
array | false | ||
» user_permissions |
array | false |
Enumerated Values
| Property | Value(s) |
|---|---|
action |
application_connect, assign, create, create_agent, delete, delete_agent, read, read_personal, share, ssh, start, stop, unassign, update, update_agent, update_personal, use, view_insights |
resource_type |
*, ai_gateway_key, ai_model_price, ai_provider, ai_seat, aibridge_interception, api_key, assign_org_role, assign_role, audit_log, boundary_log, boundary_usage, chat, chat_model_config, chat_project, chat_project_memory, connection_log, crypto_key, debug_info, deployment_config, deployment_stats, file, group, group_member, idpsync_settings, inbox_notification, license, mcp_server_config, notification_message, notification_preference, notification_template, oauth2_app, oauth2_app_code_token, oauth2_app_secret, organization, organization_member, organization_skill, prebuilt_workspace, provisioner_daemon, provisioner_jobs, replicas, system, tailnet_coordinator, template, usage_event, user, user_secret, user_skill, webpush_subscription, workspace, workspace_agent_devcontainers, workspace_agent_resource_monitor, workspace_build_orchestration, workspace_dormant, workspace_proxy |
To perform this operation, you must be authenticated. Learn more.