---
title: "Change a member's permission or answer your own invite"
method: PATCH
path: "/organization-roles/{id}"
tags: ["Organization Roles"]
---

# Change a member's permission or answer your own invite

`PATCH /organization-roles/{id}`

## Request

- Base URL: `https://api.purplegrain.com/api/v1`
- URL: `https://api.purplegrain.com/api/v1/organization-roles/{id}`
- Auth: HTTP bearer

Change a member's permission, or let an invitee accept or decline their
own invite. The role's own user may set `status` alone to `accepted` or
`declined`. Anything else, including `permission`, needs edit rights on
the business. A new permission cannot be more privileged than the
caller's own role; an owner may assign any.

## Path parameters

- `id` string, required

## Query parameters

- `include` string

## Request body

- OrganizationRoleUpdateModelAttributes: Flat attributes-adapter request body (Content-Type application/json). Attribute fields and relationships live directly under `data` (no nested `attributes` / `relationships` envelopes). Each relationship is a resource identifier object ({ id, type }). Equivalent JSON:API (nested) shape: `OrganizationRoleUpdateModel` sent as application/vnd.api+json.
  - `data` object, required
    - `permission` 'owner' | 'admin' | 'manager' | 'contractor' | 'viewer'
    - `status` 'pending' | 'accepted' | 'declined', nullable
    - `organization` object, nullable, required
      - `id` string, nullable
      - `type` 'organization', nullable
    - `user` object, nullable, required
      - `id` string, nullable
      - `type` 'user', nullable

## Response `200`

Update. When the `include` query parameter is used, the response may contain an `included` array (JSON:API) or inlined related resources (application/json).

- OrganizationRolesShowResponseAttributes
  - `data` OrganizationRoleModelAttributes: Organization role in attributes-adapter shape (Accept application/json); fields at top level.
    - `id` string
    - `type` string
    - `status` 'pending' | 'accepted' | 'declined'
    - `permission` 'owner' | 'admin' | 'manager' | 'contractor' | 'viewer'
    - `invited_email` string, nullable
    - `invited_mobile` string, nullable
    - `invited` boolean
    - `inviter_name` string: Display name of the inviter (the organization owner).
    - `updated_at` string, date-time
    - `created_at` string, date-time
    - `organization` object: Inlined when include=organization
    - `user` object: Inlined when include=user

## Other responses

- `400`: The `include` query parameter names a relationship path this endpoint does not take (JSON:API 1.1, "Inclusion of Related Resources"). One error with `code: "unknown_include"` and `source.parameter: "include"`; its `detail` names the refused path(s) and the paths the endpoint allows (the parameter's `x-include-paths`). An endpoint whose serializer whitelists no relationship refuses any path. Rolling out as monitor then enforce: until the API's `JSONAPI_UNKNOWN_INCLUDE` is `reject`, an unknown path is dropped and logged instead.
- `401`: Unauthenticated
- `403`: Forbidden
- `404`: Not Found
- `409`: Conflict — the JSON:API request document names a different resource from the URL (JSON:API 1.1 §9.2 and §9.3). `errors[0].code` is `type_mismatch` when `data.type` is not one of this endpoint's resource types (`source.pointer` is `/data/type`), or `id_mismatch` when, on an update, `data.id` is not the id in the URL (`/data/id`). Only a body sent as `application/vnd.api+json` is checked; the flat `application/json` body has no resource object. Nothing was changed. Request validation runs first: a `data.type` outside the operation's documented enum, or missing where the schema requires it, is a `400` before this check, so the 409 is seen where the documented type is a free string, or when validation is off.
- `415`: Unsupported Media Type — the request's `Content-Type` is `application/vnd.api+json` with a media type parameter the JSON:API media type does not allow (anything other than `ext` and `profile`; `; charset=utf-8` is the usual one). Send the bare media type. The error's `code` is `unsupported_media_type` and `source.header` is `Content-Type`. Until the switch is on (`JSONAPI_CONTENT_TYPE_PARAMS=reject`) such a request is let through and logged; the operation documents the response it will have.

## Changes

- **2026-10-30** `143d65e52617`: 3 info
  - added the non-success response with the status `400`
  - added the non-success response with the status `409`
  - added the non-success response with the status `415`
- **2026-10-30** `92c4663a1266`: 6 warning, 6 info
  - removed the optional property `_meta` from the response with the `404` status (media type: application/json)
  - removed the optional property `_meta` from the response with the `404` status (media type: application/vnd.api+json)
  - removed the optional property `errors/items/onboarding` from the response with the `404` status (media type: application/json)
  - removed the optional property `errors/items/onboarding` from the response with the `404` status (media type: application/vnd.api+json)
  - …8 more
- **2026-10-30** `c1bc18b1cdbc`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/purplegrain/apis/purple-grain-api/changes/organization-roles/:id/patch.md)

---

[API](https://skmtc.dev/purplegrain/apis/purple-grain-api.md) - [All operations](https://skmtc.dev/purplegrain/apis/purple-grain-api/llms.txt) - [OpenAPI document](https://skmtc.dev/purplegrain/apis/purple-grain-api/revisions/370fe2f3ed4f?raw)
