Pin a version for a scope
const url = 'https://example.com/v1/tools/example/pinned/pin';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"version":"example","scope":{"kind":"tenant"},"reason":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://example.com/v1/tools/example/pinned/pin \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "version": "example", "scope": { "kind": "tenant" }, "reason": "example" }'Pins version for scope (the tenant, an org or a project), or moves the scope’s pin to it. An agent or flow version made in a project the pin covers (the project’s own pin, then its org’s, then the tenant’s) locks the tool at the pinned version: a flow’s tool step always, an agent’s tool reference when the pinned version is in its range. A version already made keeps its lock; a pin reaches an agent or flow through its next version. The version must be registered and active. Pinning the version the scope already pins changes nothing and answers the change that set it. Every change is recorded, with who asked and why. Needs pin on the tool.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”ToolId — dotted namespace (acme.lookup-order).
Header Parameters
Section titled “Header Parameters”Caller-supplied idempotency key, scoped to the caller: the same key from someone else in the tenant is their own request (from 0.1.5). Retries with the same key return the original response byte-identical (per docs/API-ROUTE-CONVENTIONS.md §3.1). A retry sent while the first request still runs is answered 409 idempotency-key-in-flight with Retry-After, on a runtime whose store holds keys (from 0.1.5); retry after it, and you get the first request’s answer. An answer that carries a secret (a new API key or public run token, a session token, a generated signing secret) isn’t kept: a retry gets 409 idempotency-key-replay-withheld, with the first request’s status and when it succeeded (from 0.1.5). A request whose key store can’t be read before it runs is answered 503 idempotency-store-unavailable with Retry-After: nothing ran, so retry with the same key (from 0.3.0).
Request Bodyrequired
Section titled “Request Bodyrequired”object
The version to pin (registered, active).
Responses
Section titled “Responses”Pinned.
One change of a scope’s pin, kept for good: what was pinned before, what is after, who asked and why.
object
The scope’s own pin before; null when it had none.
The scope’s own pin after; null after an unpin.
Who pinned or unpinned: a user, or a service token.
object
Example
{ "scope": { "kind": "tenant" }, "action": "pin", "requestedBy": { "kind": "user" }}Malformed request body. Or scope-invalid: a segment scope, since tools pin per project, org or tenant. Or reference-out-of-scope: a project scope whose project doesn’t reach the tool (details.issues). Or tool-not-pinnable: the tool follows its server (an MCP endpoint’s catalog lists it; its metadata has the catalog’s kindgi.mcp key) or the runtime (a tool the runtime ships), so a pin couldn’t keep it still; reference it with a range.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Missing / malformed / expired / revoked bearer token.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}tool-not-found: no tool with that id, or the version isn’t registered or was unregistered.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Idempotency-Key was reused with a different body. Or pin-scope-spans-environments: the tool has a project in an environment order, and a tenant- or org-wide pin would act in every environment of the order at once; pin it per project instead. Or environment-takes-promotions: the project is a later environment of an environment order, where no agent or flow version is made, so a pin there would never act; pin the tool in the order’s first environment (details.firstProjectId). Or registry-read-only: this registry takes no writes (under kindgi dev, the pack’s files are the source); the message says what to do instead.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}tool-gone: the tool has no active version left.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The request body is over the API’s limit (request-too-large; details.maxBytes says how much).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}Server error (unmapped domain code or framework crash).
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}The Idempotency-Key store couldn’t be read before the request ran (idempotency-store-unavailable), so nothing was changed; Retry-After (whole seconds) says when to try again with the same key.
object
object
Stable machine-readable discriminant. Values match domain error codes (see docs/API-ROUTE-CONVENTIONS.md §4.3).
Optional, kind-specific.
object
Server-assigned request id; also echoed via X-Request-Id header.
Examplegenerated
{ "error": { "code": "example", "message": "example", "details": {}, "requestId": "example" }}See also
GET /v1/tools/{toolId}: Fetch a tool manifest (latest active version)GET /v1/tools/{toolId}/versions: List all versions of a toolGET /v1/tools/{toolId}/versions/{version}: Fetch a specific tool versionPOST /v1/tools/{toolId}/versions/{version}/unregister: Unregister a specific tool version- Error code
environment-takes-promotions - Error code
idempotency-store-unavailable - Error code
pin-scope-spans-environments - Error code
reference-out-of-scope - Error code
registry-read-only - Error code
request-too-large - Error code
scope-invalid - Error code
tool-gone - Error code
tool-not-found - Error code
tool-not-pinnable - Every error code