
# Set role permissions

`PUT /fapi/v1/organizations/{org_id}/roles/{role_id}/permissions` · called from the environment's sign-in host

Replaces the permission set of an organization role. Only permissions the environment allows for organization roles can be used, and administrators can grant only permissions they hold themselves. Permissions and APIs cannot be created here. Requires the authenticated user's `__Host-idp_session` cookie; if the cookie is missing, expired, or revoked, returns `401 unauthenticated`. A first-party app on another origin can instead send its front API access token (`Authorization: DPoP <token>` with a DPoP proof; see [Front API access token](/docs/api/fapi/front-api-token)). The user must be an active member of the organization with the `idp_roles:manage` permission. A user who is not a member gets `404 not_found`, so the organization's existence is not disclosed; a member without the permission gets `403 insufficient_permissions`. Organization roles must be enabled for the environment and included in its plan.

## Request

Headers:

| Header | Required | Description |
| --- | --- | --- |
| `Idp-Client` | yes | SDK identifier. |
| `Origin` | yes | Must be exactly `https://<sign-in host>`. |
| `Content-Type` | with a body | `application/json`. |
| `If-Match` | no | `"<version>"` of the role as last read; if the role has changed since, returns `412 precondition_failed` and nothing changes. |

`org_id`: the organization identifier (`org_…`). `role_id`: the role identifier (`rol_…`).

Body:

| Field | Required | Description |
| --- | --- | --- |
| `permission_ids` | yes | The full set, at most 100 permission identifiers (`perm_…`); `[]` removes all. |

## Response

`200 OK` with a new `ETag`; the body is the role (see [Get an organization role](./get)).

## Errors

| Status | Code | When |
| --- | --- | --- |
| 401 | `unauthenticated` | No valid session cookie. |
| 403 | `origin_not_allowed` | `Origin` is missing or wrong. |
| 403 | `insufficient_permissions` | The user lacks `idp_roles:manage` in the organization. |
| 403 | `plan_feature_unavailable` | The environment's plan does not include organization roles (`feature`, `required_plan`). |
| 403 | `org_custom_roles_disabled` | Organization roles are turned off for the environment. |
| 403 | `role_not_assignable` | The role, or the new set, grants a permission the user does not hold, or the user's own membership carries the role. |
| 404 | `not_found` | No such organization or organization role for this user; an environment role, an unknown, malformed or foreign identifier answers the same. |
| 409 | `organization_pending_deletion` | The organization is scheduled for deletion. |
| 412 | `precondition_failed` | `If-Match` does not name the current version, or the role changed while the request was processed. |
| 422 | `permission_not_allowed` | A permission is not allowed for organization roles. |
| 422 | `permission_reserved` | A permission is reserved for the platform. |
| 422 | `validation_failed` | The list is invalid or too long. |
| 503 | `service_unavailable` | Temporarily unavailable; retry after `Retry-After`. |

## Example

```bash
curl -X PUT https://example.keenauth.app/fapi/v1/organizations/org_01jbz6x8kq3m2n4p5r6s7t8v9a/roles/rol_01jbz6x8kq3m2n4p5r6s7t8v9w/permissions \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"permission_ids":["perm_01jbz6x8kq3m2n4p5r6s7t8v9b"]}'
```
