---
title: "Update an MCP staff key (only the fields sent)"
description: "Applies only the fields present in the body, and only those that differ from the stored key.\nOwner-only (saas_admin_users role 'owner'): setting a global grant (any wildcardRole — the only\nglobal grant), any write grant, re-activating an inactive key (isActive true),\nreassigning staffMemberId, and extending expiresAt on a global or expired key. Platform admins\nmay rename, deactivate, remove global grants, and shorten expiry. A concurrent change answers\n409. The admin log records server-built before/after values only.\n"
---

> Documentation Index
> Fetch the complete documentation index at: https://developer.channelautomations.com/llms.txt
> Use this file to discover all available pages before exploring further.

Path: Channel Automation API › Platform Admin

`PATCH /api/admin/mcp-permissions/keys/{keyId}`

Applies only the fields present in the body, and only those that differ from the stored key.
Owner-only (saas_admin_users role 'owner'): setting a global grant (any wildcardRole — the only
global grant), any write grant, re-activating an inactive key (isActive true),
reassigning staffMemberId, and extending expiresAt on a global or expired key. Platform admins
may rename, deactivate, remove global grants, and shorten expiry. A concurrent change answers
409. The admin log records server-built before/after values only.

## Authentication

- `BearerAuth`, http, header `Authorization`, format `JWT`

## Path parameters

- `keyId` (`patch/api/admin/mcp-permissions/keys/keyId.path.keyId`; string, required)
  - format `uuid`

## Request body

_Required._

- `label` (`patch/api/admin/mcp-permissions/keys/keyId.label`; string, optional)
- `staffMemberId` (`patch/api/admin/mcp-permissions/keys/keyId.staffMemberId`; string, optional, nullable)
  - format `uuid`
- `wildcardRole` (`patch/api/admin/mcp-permissions/keys/keyId.wildcardRole`; string, optional, nullable) — Access to every workspace (owner only to set)
  - one of `"read"`, `"write"`
- `defaultRole` (`patch/api/admin/mcp-permissions/keys/keyId.defaultRole`; string, optional, deprecated) — Legacy; 'none' clears a pre-migration value, read/write is applied as wildcardRole
  - one of `"none"`, `"read"`, `"write"`
- `isActive` (`patch/api/admin/mcp-permissions/keys/keyId.isActive`; boolean, optional)
- `expiresAt` (`patch/api/admin/mcp-permissions/keys/keyId.expiresAt`; string, optional) — Future, at most 365 days away
  - format `date-time`

## Example request

```json
{
  "label": "string",
  "staffMemberId": "138ee295-38b9-456a-b430-39719940f4cd",
  "wildcardRole": "read",
  "defaultRole": "none",
  "isActive": true,
  "expiresAt": "2019-08-24T14:15:22Z"
}
```

## Code samples

### cURL

```bash
curl --request PATCH \
  --url 'https://api.channelautomation.com/api/admin/mcp-permissions/keys/<keyId>' \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "label": "string",
  "staffMemberId": "138ee295-38b9-456a-b430-39719940f4cd",
  "wildcardRole": "read",
  "defaultRole": "none",
  "isActive": true,
  "expiresAt": "2019-08-24T14:15:22Z"
}
'
```

### TypeScript

```typescript
const url = 'https://api.channelautomation.com/api/admin/mcp-permissions/keys/<keyId>';
const options = {
  method: 'PATCH',
  headers: {'Content-Type': 'application/json', Authorization: 'Bearer <token>'},
  body: JSON.stringify({
    label: 'string',
    staffMemberId: '138ee295-38b9-456a-b430-39719940f4cd',
    wildcardRole: 'read',
    defaultRole: 'none',
    isActive: true,
    expiresAt: '2019-08-24T14:15:22Z'
  })
};

fetch(url, options)
  .then(res => res.json())
  .then(json => console.log(json))
  .catch(err => console.error(err));
```

### Python

```python
import requests

url = "https://api.channelautomation.com/api/admin/mcp-permissions/keys/<keyId>"

payload = {
    "label": "string",
    "staffMemberId": "138ee295-38b9-456a-b430-39719940f4cd",
    "wildcardRole": "read",
    "defaultRole": "none",
    "isActive": True,
    "expiresAt": "2019-08-24T14:15:22Z"
}
headers = {
    "Content-Type": "application/json",
    "Authorization": "Bearer <token>"
}

response = requests.patch(url, json=payload, headers=headers)

print(response.text)
```

## Responses

### 200

{ success, data: key } — unchanged key with message 'No changes' when nothing differed

### 400

No fields, or an invalid value

### 403

OWNER_ROLE_REQUIRED

### 404

Key not found

### 409

The key changed while saving; reload and retry

### 500

Internal server error

#### Example

```json
{
  "error": "Internal server error",
  "details": "string",
  "success": false
}
```

- `error` (`patch/api/admin/mcp-permissions/keys/keyId.response.500.error`; string, optional)
  - example `"Internal server error"`
- `details` (`patch/api/admin/mcp-permissions/keys/keyId.response.500.details`; string, optional)
- `success` (`patch/api/admin/mcp-permissions/keys/keyId.response.500.success`; boolean, optional)
  - example `false`

### 503

MCP_KEY_EXPIRY_NOT_SET_UP (expiresAt sent before migration 20261005a)


Source: https://developer.channelautomations.com/api/patch-api-admin-mcp-permissions-keys-key-id/index.md
