# Update a global integrator Modify a global integrator's metadata, scopes, capabilities, or rate limits

`PUT /api/configuration/admin/integrators/{id}`

- **Success:** `200 OK`
- **Products:** not restricted by product
- **Features:** Gladstone Admin Areas (`ADMIN`)

HTML version: [Update a global integrator Modify a global integrator's metadata, scopes, capabilities, or rate limits](https://support.gladstonesoftware.cloud/reference/configuration/update-a-global-integrator-modify-a-global-integrators-metadata-scopes-capabilit)

## Overview

Rewrites a global integrator's configuration: its display metadata, the web origin its keys may be used from, the scopes and capability flags stamped onto its tokens, its rate limits, and whether it is active at all.

**This is a full replacement, not a patch.** Every field in the body is written unconditionally. There is no "leave this alone" — a field you omit is written as its JSON default, which means `null` for the strings and **`false` for every boolean**. Sending `{"name": "Acme", "origin": "https://acme.example"}` does not just rename the integrator: it clears `description`, `logoUrl` and `allowedScopes`, sets `canRead`, `canWrite`, `canDelete` and `isBillable` to false, zeroes both rate limits, and sets `isActive` to false — which retires the integrator for every tenant using it. **Always read the integrator first, change the fields you mean to change, and send the whole object back.**

Changes reach live traffic at different speeds:

- **Scopes and capability flags** are baked into the JWT when a token is minted, so an integration holding a valid access token keeps its old scopes until that token expires. New tokens carry the new values immediately.
- **`isActive` false** stops new tokens being issued, but can take up to five minutes to take effect.
- **Rate limits** are checked on every token request, so a change takes effect on the next call.

API keys themselves are never touched by this call: nothing is revoked, nothing is reissued, and no key value is returned.

This endpoint is restricted to Gladstone Support: it rejects any caller whose token does not carry the `ADMIN` feature claim. Tenants cannot vary a global integrator's settings for themselves — the record is shared by every tenant that has activated it, and a change here applies to all of them at once.

## Endpoint

`PUT {base_url}/api/configuration/admin/integrators/{id}`

`{base_url}` is the environment URL issued to your integration. See [Authenticating with Gladstone APIs](../../guides/authenticating-with-gladstone-apis.md).

## Path parameters

| Name | Type | Required | Description |
|------|------|----------|-------------|
| `id` | integer (int32) | Yes | The identifier of the integrator to update, from the `id` field of [List all global integrators](list-all-global-integrators-get-every-global-integrator-registered-across-the-pl.md). The record must have `isGlobal` true; an id belonging to a tenant's private integrator is rejected with `404` rather than being updated. |

## Request body

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `name` | string | Yes | The integrator's display name, shown to operators choosing an integration from the catalogue. Must be present and non-empty — omitting it, or sending `""` or `null`, fails validation with `400`. Not required to be unique, so two integrators can share a name; only `id` distinguishes them. Maximum 255 characters, but a longer value fails with `500` rather than `400`. |
| `description` | string | No | Free-text explanation of what the integration does, for the same operator-facing catalogue. Unbounded length. Omitting it or sending `null` clears whatever description the record had — send the existing value back if you want to keep it. |
| `origin` | string | Yes | The single web origin (scheme and host, for example `https://booking.acme.example`) that browser-based use of this integrator's keys is tied to. When a token request arrives carrying an `Origin` header, it must equal this value — compared case-insensitively, ignoring one trailing slash — or the request is rejected with `401`. A token request with **no** `Origin` header skips the check entirely, so this is a browser guard, not a server-to-server one. Only one origin is supported; there is no list form and no wildcard. Must be present and non-empty (`400` otherwise). Maximum 255 characters, but a longer value fails with `500` rather than `400`. |
| `logoUrl` | string | No | Absolute URL of a logo for the integrator, for display alongside its name. Maximum 500 characters; a longer value fails with `500` rather than `400`. Not fetched or validated by the platform. Omitting it or sending `null` clears the existing value. |
| `isBillable` | boolean | No | Whether usage under this integrator is chargeable. The value is copied onto every token minted from the integrator's keys as a `billable` claim, which is how usage is attributed. **Omitting this field sets it to false**, silently making a chargeable integration free. |
| `allowedScopes` | string | No | The features this integrator may reach, as a **JSON array serialised into a string** — for example `"[\"FOH\",\"ONLINEBOOK\"]"`, not a JSON array in the body. Each entry is emitted twice on every new token, once as a features claim and once as a products claim, because gateway routes match on both. Nothing here is validated at write time: if the string is not parseable as a JSON array of strings, tokens are minted with no scope claims at all and every route rejects them with `403`. Omitting the field or sending `null` has the same effect — it clears the scopes and leaves the integrator able to authenticate but unable to call anything. Unbounded length. |
| `canRead` | boolean | No | Whether this integrator may issue `GET`, `HEAD` and `OPTIONS` requests. Emitted as a `can_read` claim on new tokens and enforced by every endpoint: a partner token without `can_read` true gets `403` with the plain-text body `Partner token lacks can_read capability.` on any read. **Omitting this field sets it to false**, which locks the integration out of every read endpoint on its next token. |
| `canWrite` | boolean | No | Whether this integrator may issue `POST`, `PUT` and `PATCH` requests. Emitted as a `can_write` claim; a partner token without it true gets `403` with the body `Partner token lacks can_write capability.` **Omitting this field sets it to false.** |
| `canDelete` | boolean | No | Whether this integrator may issue `DELETE` requests. Emitted as a `can_delete` claim; a partner token without it true gets `403` with the body `Partner token lacks can_delete capability.` Only `DELETE` maps to this flag — a soft delete exposed as a `POST` or `PUT` is governed by `canWrite` instead. **Omitting this field sets it to false.** |
| `rateLimitPerMinute` | integer (int32) | No | Maximum token requests allowed per API key in a one-minute window. Counted per key, not per integrator, so each tenant that activated this integrator gets its own budget. Exceeding it returns `429` with a `Retry-After` header. **`0` means unlimited** — and since omitting the field defaults it to `0`, leaving it out removes the limit rather than keeping it. Negative values are rejected with `400`. The window is a fixed calendar minute, not a sliding one, so a burst can span two windows. |
| `rateLimitPerHour` | integer (int32) | No | Maximum token requests allowed per API key in a one-hour window, checked after the per-minute limit passes. **`0` means unlimited**, which is also what omitting the field gives you. Negative values are rejected with `400`. Set this above `rateLimitPerMinute` × 60 and it can never bite; set it below and it is the limit that actually applies. |
| `isActive` | boolean | No | Whether the integrator may be used at all. Setting it false is equivalent to calling [Soft-delete a global integrator](soft-delete-a-global-integrator-mark-a-global-integrator-inactive-without-removi.md) — key validation requires an active integrator, so every tenant's key stops minting tokens within five minutes, though existing access tokens live out their term. Setting it back to true restores those keys, because they were never revoked. **Omitting this field sets it to false and retires the integrator**, which is the single most damaging mistake you can make on this endpoint. |

## Sample request

```bash title="cURL"
curl -X PUT '{base_url}/api/configuration/admin/integrators/{id}' \
  -H 'Authorization: Bearer {accessToken}' \
  -H 'X-Use-SSO: true' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "string",
  "description": "string",
  "origin": "string",
  "logoUrl": "string",
  "isBillable": true,
  "allowedScopes": "string",
  "canRead": true,
  "canWrite": true,
  "canDelete": true,
  "rateLimitPerMinute": 1,
  "rateLimitPerHour": 1,
  "isActive": true
}'
```

## Response fields

| Field | Type | Description |
|-------|------|-------------|
| `id` | integer (int32) | The integrator's identifier — the same value you passed in the path. It is never reassigned by an update. |
| `name` | string | The name as saved, echoing what you sent. |
| `description` | string | The description as saved — `null` if you omitted the field, which clears it. |
| `origin` | string | The allowed origin as saved, echoing what you sent. |
| `logoUrl` | string | The logo URL as saved — `null` if you omitted the field. |
| `isGlobal` | boolean | Always `true` here: the update is rejected with `404` unless the target is a global integrator, and this flag cannot be changed by any endpoint. |
| `isBillable` | boolean | The billable flag as saved — `false` if you omitted the field. |
| `environmentId` | integer (int32) | Always `null` for a global integrator: the catalogue record belongs to no tenant, even though the API keys created when tenants activate it do. This is why keys from a global integrator mint API-only tokens with no tenant claims and cannot be used for member login or member-token refresh. |
| `allowedScopes` | string | The scope string as saved, byte for byte as you sent it — `null` if you omitted the field. It is not parsed or normalised, so this response confirms what was stored, not that it is usable. |
| `canRead` | boolean | The read capability as saved — `false` if you omitted the field, which blocks the integration from every `GET` on its next token. |
| `canWrite` | boolean | The write capability as saved — `false` if you omitted the field. |
| `canDelete` | boolean | The delete capability as saved — `false` if you omitted the field. |
| `rateLimitPerMinute` | integer (int32) | The per-minute budget as saved — `0`, meaning unlimited, if you omitted the field. |
| `rateLimitPerHour` | integer (int32) | The per-hour budget as saved — `0`, meaning unlimited, if you omitted the field. |
| `isActive` | boolean | The active flag as saved. Check this on every response: `false` means the integrator is now retired for every tenant, and it is `false` whenever the field was omitted from the body. |
| `createdOn` | string (date-time) | UTC timestamp the integrator was first registered. Unchanged by this call. |
| `modifiedOn` | string (date-time) | UTC timestamp of this update, set server-side. `null` only if the record has somehow never been updated, which cannot be the case in a successful response from this endpoint. |

## Sample response

```json title="200 OK"
{
  "id": 12345,
  "name": "string",
  "description": "string",
  "origin": "string",
  "logoUrl": "string",
  "isGlobal": true,
  "isBillable": true,
  "environmentId": 12345,
  "allowedScopes": "string",
  "canRead": true,
  "canWrite": true,
  "canDelete": true,
  "rateLimitPerMinute": 1,
  "rateLimitPerHour": 1,
  "isActive": true,
  "createdOn": "2026-08-14T19:00:00Z",
  "modifiedOn": "2026-08-14T19:00:00Z"
}
```

## Errors

| Status | Meaning | When |
|--------|---------|------|
| `400` | Bad request | Validation failed: `name` or `origin` missing, empty or null, or either rate limit is negative. The body is a validation problem document (`application/problem+json`) with an `errors` map keyed by field name. Nothing is written. |
| `403` | Forbidden | Your token does not carry the `ADMIN` feature claim. The response has no body. This endpoint is reserved for Gladstone Support. |
| `404` | Not found | No partner exists with that id, **or** the id belongs to a private integrator rather than a global one. Despite what you may expect from the endpoint summary, a non-global target is a `404` here, not a `400`. The response has no body. |
| `500` | Internal server error | An unexpected server-side failure, including a `name` over 255 characters, an `origin` over 255 or a `logoUrl` over 500 — those limits are not validated up front, so they surface as a `500` rather than a `400`. The body is empty and nothing is written. |
