---
title: "Turn the join link on or off, and set its role and expiry"
method: PATCH
path: "/organizations/{organization_id}/join-link"
tags: ["Organization Join Links"]
---

# Turn the join link on or off, and set its role and expiry

`PATCH /organizations/{organization_id}/join-link`

## Request

- Base URL: `https://api.purplegrain.com/api/v1`
- URL: `https://api.purplegrain.com/api/v1/organizations/{organization_id}/join-link`
- Auth: HTTP bearer

Turns the business's join link on or off, and sets the role a holder
joins with and when the link expires. Anyone holding the link can join
the business in that role, after they confirm a mobile number on
PurpleGrain's own page.

`enabled: true` turns it on. Enabling mints a new link with a fresh code
when the business has no link, or the current link is off. Enabling a
link that is already on keeps the code. `enabled: false` turns the live
link off and keeps the row. `role` and `expiry` change the live link in
place: the code stays the same, and a new `expiry` restarts its clock
from now. Switching off a business that has no link is a 404. Only an
**owner** may call this. API keys are refused. Read the current link
with `getOrganizationJoinLink`.

## Path parameters

- `organization_id` string, required

## Request body

- OrganizationJoinLinkUpdateModelAttributes: Flat attributes-adapter request body (Content-Type application/json): the same optional fields as `OrganizationJoinLinkUpdateModel`, directly under `data`.
  - `data` object, required
    - `enabled` boolean
    - `role` 'member' | 'viewer'
    - `expiry` '24h' | '7d' | '30d' | 'never'

## Response `200`

The join link after the change.

- OrganizationJoinLinkShowResponseAttributes
  - `data` OrganizationJoinLinkModelAttributes: A business's join link in attributes-adapter shape (`application/json`); fields at the top level.
    - `id` string
    - `type` string
    - `code` string
    - `url` string
    - `role` 'member' | 'viewer'
    - `expiry` '24h' | '7d' | '30d' | 'never'
    - `expires_at` string, date-time, nullable
    - `enabled` boolean
    - `status` 'active' | 'expired' | 'off'
    - `uses_count` integer
    - `created_at` string, date-time
    - `updated_at` string, date-time

## Other responses

- `401`: Unauthenticated
- `403`: Forbidden — caller is not an owner of the organization.
- `404`: Switching off a business that has no join link, or the business does not exist.
- `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.
- `422`: An unknown role or expiry.

## Changes

- **2026-10-30** `143d65e52617`: 2 info
  - added the non-success response with the status `409`
  - added the non-success response with the status `415`
- **2026-10-30** `92c4663a1266`: 12 warning, 12 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 `_meta` from the response with the `422` status (media type: application/json)
  - removed the optional property `_meta` from the response with the `422` status (media type: application/vnd.api+json)
  - …20 more
- **2026-10-30** `c1bc18b1cdbc`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/purplegrain/apis/purple-grain-api/changes/organizations/:organization_id/join-link/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)
