# Update API key

> PATCH /api-keys/:id — dashboard-only. Key permissions are changed in the dashboard; an API key cannot re-scope a key.

`PATCH /api-keys/:id`

> **Warning:** **Dashboard-only.** A key's permissions are changed on the website. A request authenticated with an API key is refused with `403 dashboard_only` — "API keys can only be created, edited and revoked from the SendPing dashboard, not with an API key." — no matter what permission that key holds. Edit a key from the dashboard under **API Keys**.

> **Note:** This is a **breaking change**. Automation that used to re-scope keys with a `full_access` key now receives `403 dashboard_only`; a key could otherwise widen its own permissions. The official SDKs deliberately expose no method for this endpoint.

Updates an API key in place — no need to mint a new token to change what an existing key may do. Omitted fields stay unchanged. The secret token itself is immutable and never re-shown: to rotate credentials, create a new key and revoke this one. The reference below describes the request the dashboard makes on your behalf with a signed-in session — it is not callable with an API key.

**Path parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | Yes | The API key ID as returned by [`GET /api-keys`](https://www.sendping.co/docs/api/api-keys-list) — a numeric string (e.g. `1042`), not a UUID. A non-numeric id returns `not_found` (404). |

**Body parameters**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | No | A new label for the key. |
| `permission` | full_access | sending_access | No | The new access level. Setting `full_access` also clears any domain restriction — full-access keys always work across all your domains. |
| `domain_ids` | string[] | null | No | Replace the key’s domain restriction. Only valid with `sending_access`. Send `null` (or an empty array) to allow all domains. Omit the field to leave the current restriction unchanged. |
| `domain_id` | string | No | Legacy single-domain form of `domain_ids`. Provide one or the other, not both. |

### Response

For the dashboard session, the updated key is returned (the secret is never re-shown — `token` is the non-secret prefix):

```json
{
  "id": "1042",
  "object": "api_key",
  "name": "Production server",
  "token": "mb_AbC12",
  "permission": "sending_access",
  "domain_id": "b8f9c2aa-4c11-4f24-9d55-1f7a2b3c4d5e",
  "domain_ids": ["b8f9c2aa-4c11-4f24-9d55-1f7a2b3c4d5e"],
  "created_at": "2026-06-23T10:00:00.000Z",
  "last_used_at": "2026-06-25T17:09:51.813Z"
}
```

### Response to an API-key caller

```json
{
  "statusCode": 403,
  "name": "dashboard_only",
  "message": "API keys can only be created, edited and revoked from the SendPing dashboard, not with an API key."
}
```

> **Note:** Errors: `dashboard_only` (403) for **every** API-key caller — this check runs before any validation; `not_found` if the key does not exist, is revoked, or is not yours; `validation_error` if no updatable field is provided, `name` is empty, `permission` is invalid, both `domain_id` and `domain_ids` are provided, a domain restriction is combined with `full_access`, or `domain_ids` references a domain that is not yours.
