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)
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.
isActivefalse 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.
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. 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 — 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
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
{
"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. |