openapi: 3.2.0 info: title: 'GTM API public contract: gtm.service.id API Keys API' description: 'Identity, access and money: users, teams and members, API keys, OAuth clients and authorizations, billing products, subscriptions, transactions and payment methods, notifications, TLS certificates and support requests.' version: '1.0' contact: name: GTM API url: https://gtm-api.com email: support@gtm-api.com license: name: Proprietary url: https://gtm-api.com/license servers: - url: https://app.gtm-api.com/id/v4 description: Production, through the app.gtm-api.com gateway security: - BearerJwt: [] TeamSid: [] tags: - name: API Keys description: Registry package `mcp.id/api_keys`, served on MCP mount `id.access`. paths: /api/api-keys: post: operationId: create_api_key summary: Create API key description: 'Issue a new API key and return the full secret in the create envelope''s plaintext_token EXACTLY ONCE. It is unrecoverable, so hand it to the user immediately and never log or echo it; if lost, rotate. BOTH grant axes are clamped to the ISSUER''s own current authority (403, reason grant_exceeds_ceiling): permissions must sit inside the caller''s token set (''*'' only for an unrestricted issuer; on delegation, inside the parent key''s set), and account_sids inside the caller''s account slice - a sliced caller cannot pass null ("all accounts") and must send an explicit list within their slice. Verify re-intersects both axes with the issuer''s CURRENT authority, so narrowing the issuer narrows every key they minted. Default expires_at = now + 3 years; pass null for a perpetual key. Natural key (team_sid, name) among non-revoked keys → a duplicate returns already_exists with the existing key (and NO secret). Contract: - MCP tool `create_api_key`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `create`, response envelope `create`. - Flags: dangerous: the MCP layer gates it behind a preview/commit token, and the effect cannot be undone through this API.' tags: - API Keys requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateApiKeyRequest' responses: '200': description: '`create` success envelope.' content: application/json: schema: $ref: '#/components/schemas/CreateApiKeyResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: create_api_key x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: create x-gtm-envelope: create x-gtm-availability: ga x-gtm-dangerous: true x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: typical /api/api-keys/metrics: post: operationId: get_api_keys_metrics summary: API key metrics description: 'Period-bound counts of the team''s keys by status, plus issuance / expiry tallies inside the window (created_in_period, expired_in_period). Requires period {from, to}. Optional filter. Counts key rows, not key traffic. Contract: - MCP tool `get_api_keys_metrics`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `metrics`, response envelope `metrics`. - Flags: read only.' tags: - API Keys requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/GetApiKeysMetricsRequest' responses: '200': description: '`metrics` success envelope.' content: application/json: schema: $ref: '#/components/schemas/GetApiKeysMetricsResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: get_api_keys_metrics x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: metrics x-gtm-envelope: metrics x-gtm-availability: ga x-gtm-dangerous: false x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: typical /api/api-keys/search: post: operationId: search_api_keys summary: Search API keys description: 'List the team''s API keys for an access audit: which keys exist, what each can do (permissions), their status, when each was last_used_at and when each expires. Filter by status for live vs dead keys, by last_used_at.lt for stale keys to revoke at offboarding, or by expires_at for keys expiring soon. The secret is never returned (only token_prefix + token_last4). include:["metrics"] attaches per-key counts; page_size:0 returns counts only. Contract: - MCP tool `search_api_keys`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `search`, response envelope `search`. - Flags: read only.' tags: - API Keys requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/SearchApiKeysRequest' responses: '200': description: '`search` success envelope.' content: application/json: schema: $ref: '#/components/schemas/SearchApiKeysResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: search_api_keys x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: search x-gtm-envelope: search x-gtm-availability: ga x-gtm-dangerous: false x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: typical /api/api-keys/{sid}: get: operationId: get_api_key summary: Get API key description: 'Fetch a single API key by sid, with optional metrics include. Returns token_prefix + token_last4 for display; the secret is unrecoverable (use rotate_api_key to mint a new one). Contract: - MCP tool `get_api_key`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `get`, response envelope `get`. - Flags: read only.' tags: - API Keys parameters: - name: sid in: path required: true description: Path segment `{sid}`. schema: type: string minLength: 18 maxLength: 18 pattern: ^id_ak_ - name: include[] in: query required: false description: Query parameter `include`. style: form explode: true schema: type: array items: type: string enum: - metrics responses: '200': description: '`get` success envelope.' content: application/json: schema: $ref: '#/components/schemas/GetApiKeyResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: get_api_key x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: get x-gtm-envelope: get x-gtm-availability: ga x-gtm-dangerous: false x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: trivial patch: operationId: update_api_key summary: Update API key description: 'Partial update of name / permissions / account_sids (the key''s identity and secret are untouched; use rotate_api_key to change the secret). Each list is a FULL replacement, clamped to the STORED issuer''s current authority on its axis (403, reason grant_exceeds_ceiling): permissions inside their token set, account_sids inside their slice (null = all accounts, grantable only under an unrestricted issuer slice). At least one field is required. A change takes effect at once: id tells every channel service to forget the key''s cached verdict (a peer the fan-out cannot reach falls back to its 5-minute cache). Contract: - MCP tool `update_api_key`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `update`, response envelope `update`. - Flags: none.' tags: - API Keys parameters: - name: sid in: path required: true description: API key sid (id_ak_…). schema: type: string minLength: 18 maxLength: 18 pattern: ^id_ak_ description: API key sid (id_ak_…). requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/UpdateApiKeyRequest' responses: '200': description: '`update` success envelope.' content: application/json: schema: $ref: '#/components/schemas/UpdateApiKeyResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: update_api_key x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: update x-gtm-envelope: update x-gtm-availability: ga x-gtm-dangerous: false x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: typical delete: operationId: delete_api_key summary: Revoke API key description: 'Revoke a key (simple soft-delete): status=revoked, deleted_at set. The key stops verifying at once: id tells every channel service to forget its cached verdict (a peer the fan-out cannot reach falls back to its 5-minute cache). Irreversible: a revoked key never re-activates; issue a fresh one. Idempotent: re-deleting → already_deleted. Contract: - MCP tool `delete_api_key`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `delete`, response envelope `delete_simple`. - Flags: dangerous: the MCP layer gates it behind a preview/commit token, and the effect cannot be undone through this API.' tags: - API Keys parameters: - name: sid in: path required: true description: Path segment `{sid}`. schema: type: string minLength: 18 maxLength: 18 pattern: ^id_ak_ responses: '200': description: '`delete_simple` success envelope.' content: application/json: schema: $ref: '#/components/schemas/DeleteApiKeyResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: delete_api_key x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: delete x-gtm-envelope: delete_simple x-gtm-availability: ga x-gtm-dangerous: true x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: trivial /api/api-keys/{sid}/rotate: post: operationId: rotate_api_key summary: Rotate API key description: 'Swap the key''s secret IN PLACE and return the new plaintext in result.plaintext_token EXACTLY ONCE: hand it to the user, never log it, unrecoverable. The key''s sid / name / permissions / expires_at are unchanged. The previous secret stays valid until result.previous_token_expires_at (now + grace_seconds, default 24h) so the agent can update config without downtime. Use when a secret leaks or before offboarding. NOT idempotent: each call mints a brand-new secret. Rotating a revoked/expired key → 409. Contract: - MCP tool `rotate_api_key`, registry package `mcp.id/api_keys`, mount `id.access`. - Operation `action`, response envelope `action`. - Flags: dangerous: the MCP layer gates it behind a preview/commit token, and the effect cannot be undone through this API.' tags: - API Keys parameters: - name: sid in: path required: true description: API key sid (id_ak_…). schema: type: string minLength: 18 maxLength: 18 pattern: ^id_ak_ description: API key sid (id_ak_…). requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/RotateApiKeyRequest' responses: '200': description: '`action` success envelope.' content: application/json: schema: $ref: '#/components/schemas/RotateApiKeyResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: rotate_api_key x-gtm-mcp-mount: id.access x-gtm-entity: api_keys x-gtm-operation: action x-gtm-envelope: action x-gtm-availability: ga x-gtm-dangerous: true x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: complex components: schemas: SearchApiKeysResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - search items: type: array items: type: object properties: item: type: object properties: sid: type: string team_sid: type: string name: type: string token_prefix: type: string token_last4: type: string permissions: type: array items: type: string account_sids: type: - array - 'null' items: type: string status: type: string enum: - active - revoked - expired expires_at: type: - string - 'null' last_used_at: type: - string - 'null' created_by: type: object properties: actor_type: type: string enum: - user - support - api_key - system - agent actor_sid: type: - string - 'null' team_sid: type: string actor_name: type: - string - 'null' description: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job. oauth_client_sid: type: - string - 'null' description: The acting OAuth client (id_oc_*); null off the OAuth path. reason: type: - string - 'null' description: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise. permissions: type: object additionalProperties: {} description: 'Internal audit context: the grant set the actor held at write time. Not a contract.' cluster_id: type: - integer - 'null' description: 'Internal audit context: the cluster that served the write.' trace_id: type: - string - 'null' description: 'Internal audit context: the trace id of the request that wrote the row.' required: - actor_type - actor_sid - team_sid - permissions created_at: type: string updated_at: type: string deleted_at: type: - string - 'null' plaintext_token: type: - string - 'null' required: - sid - team_sid - name - token_prefix - token_last4 - permissions - account_sids - status - expires_at - last_used_at - created_by - created_at - updated_at - deleted_at included: type: object additionalProperties: {} required: - item - included pagination: type: object properties: next_cursor: type: - string - 'null' has_more: type: boolean total_count: type: - integer - 'null' required: - next_cursor - has_more - total_count applied_filters: type: object additionalProperties: {} includes: type: array items: type: string meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms counts: type: object properties: total_count: type: number groups: type: object additionalProperties: {} required: - total_count - groups required: - success - operation - items - pagination - applied_filters - includes - meta SearchApiKeysRequest: type: object description: Request body of `search_api_keys`. properties: filter: type: object properties: sid: type: object properties: eq: type: string in: type: array items: type: string additionalProperties: false status: type: object properties: eq: type: string enum: - active - revoked - expired ne: type: string enum: - active - revoked - expired in: type: array items: type: string enum: - active - revoked - expired nin: type: array items: type: string enum: - active - revoked - expired additionalProperties: false name: type: object properties: eq: type: string additionalProperties: false description: Match on the human-readable key name. created_by_actor_sid: type: object properties: eq: type: string in: type: array items: type: string additionalProperties: false description: 'Issuer slice: keys created by this teammate (us_mb_) or parent key (id_ak_); offboarding.' expires_at: type: object properties: gte: type: string lte: type: string gt: type: string lt: type: string is_null: type: boolean additionalProperties: false description: is_null:true = perpetual keys; range = expiring-between. last_used_at: type: object properties: gte: type: string lte: type: string gt: type: string lt: type: string is_null: type: boolean additionalProperties: false description: is_null:true = never used; lt = stale keys. created_at: type: object properties: gte: type: string lte: type: string gt: type: string lt: type: string additionalProperties: false deleted_at: type: object properties: gte: type: string lte: type: string is_null: type: boolean additionalProperties: false description: 'Default scope is { is_null: true } (live rows).' include: type: array items: type: string enum: - metrics description: Relations to eager-load (see entity Includes). sort: type: object properties: field: type: string enum: - created_at - last_used_at - expires_at - name direction: type: string enum: - asc - desc description: Default desc. required: - field page_size: type: integer minimum: 0 maximum: 500 description: 0..500, default 50. page_size=0 = count-only, page_size=1 = getFirst. cursor: type: - string - 'null' description: Opaque forward cursor from a previous response pagination.next_cursor. McpError: type: object properties: success: type: boolean enum: - false error: type: object properties: code: type: string enum: - validation_failed - nothing_to_update - not_found - relation_not_found - invalid_transition - limit_exceeded - payment_required - duplicate_rejected - conflict - delete_blocked - unauthorized - forbidden - rate_limited - internal_error - service_unavailable - not_implemented message: type: string recoverable: type: boolean suggestion: type: string field_errors: type: object additionalProperties: type: array items: type: object properties: rule: type: string message: type: string required: - rule - message blockers: type: array items: type: object properties: type: type: string description: Machine-readable blocker type (active_flow, pending_tasks, …). severity: type: string enum: - hard - soft description: hard = external action required; soft = acknowledge is enough. description: type: string entity_sid: type: - string - 'null' count: type: integer resolution: type: string description: 'Hard: tool name to call. Soft: code for acknowledge[].' resolution_hint: type: string required: - type - severity - description - entity_sid - resolution - resolution_hint context: type: object additionalProperties: {} required: - code - message - recoverable meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - error UpdateApiKeyResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - update item: type: object properties: sid: type: string team_sid: type: string name: type: string token_prefix: type: string token_last4: type: string permissions: type: array items: type: string account_sids: type: - array - 'null' items: type: string status: type: string enum: - active - revoked - expired expires_at: type: - string - 'null' last_used_at: type: - string - 'null' created_by: type: object properties: actor_type: type: string enum: - user - support - api_key - system - agent actor_sid: type: - string - 'null' team_sid: type: string actor_name: type: - string - 'null' description: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job. oauth_client_sid: type: - string - 'null' description: The acting OAuth client (id_oc_*); null off the OAuth path. reason: type: - string - 'null' description: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise. permissions: type: object additionalProperties: {} description: 'Internal audit context: the grant set the actor held at write time. Not a contract.' cluster_id: type: - integer - 'null' description: 'Internal audit context: the cluster that served the write.' trace_id: type: - string - 'null' description: 'Internal audit context: the trace id of the request that wrote the row.' required: - actor_type - actor_sid - team_sid - permissions created_at: type: string updated_at: type: string deleted_at: type: - string - 'null' plaintext_token: type: - string - 'null' required: - sid - team_sid - name - token_prefix - token_last4 - permissions - account_sids - status - expires_at - last_used_at - created_by - created_at - updated_at - deleted_at updated_fields: type: array items: type: string previous_values: type: object additionalProperties: {} meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - operation - item - updated_fields - previous_values - meta RotateApiKeyRequest: type: object description: Request body of `rotate_api_key`. properties: grace_seconds: type: integer minimum: 0 maximum: 604800 description: 0..604800 (≤7d); omit = 24h default; 0 = immediate cutover. UpdateApiKeyRequest: type: object description: Request body of `update_api_key`. properties: name: type: string minLength: 1 maxLength: 255 permissions: type: array items: type: string maxLength: 128 description: FULL replacement of the key's permission list. account_sids: type: - array - 'null' items: type: string minLength: 18 maxLength: 18 pattern: ^(ln_ac_|em_ac_) minItems: 1 description: FULL replacement of the key's account slice; null = all team accounts. An empty list is refused (422). DeleteApiKeyResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - delete item: type: object additionalProperties: {} already_deleted: type: boolean soft_deleted: type: boolean retained: type: array items: type: string meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - operation - item - already_deleted - soft_deleted - retained - meta GetApiKeysMetricsResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - metrics metrics: type: object properties: filter: type: object additionalProperties: {} period: type: object properties: from: type: string to: type: string required: - from - to aggregated: type: object properties: counts: type: object additionalProperties: {} metrics: type: object properties: created_in_period: type: number expired_in_period: type: number last_used_at: type: - string - 'null' required: - created_in_period - expired_in_period - last_used_at metrics: type: object properties: created_in_period: type: number expired_in_period: type: number last_used_at: type: - string - 'null' required: - created_in_period - expired_in_period - last_used_at applied_filters: type: object additionalProperties: {} meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - operation - metrics - meta RotateApiKeyResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - action action: type: string description: kebab-case verb; matches the route segment. item: type: - object - 'null' properties: sid: type: string team_sid: type: string name: type: string token_prefix: type: string token_last4: type: string permissions: type: array items: type: string account_sids: type: - array - 'null' items: type: string status: type: string enum: - active - revoked - expired expires_at: type: - string - 'null' last_used_at: type: - string - 'null' created_by: type: object properties: actor_type: type: string enum: - user - support - api_key - system - agent actor_sid: type: - string - 'null' team_sid: type: string actor_name: type: - string - 'null' description: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job. oauth_client_sid: type: - string - 'null' description: The acting OAuth client (id_oc_*); null off the OAuth path. reason: type: - string - 'null' description: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise. permissions: type: object additionalProperties: {} description: 'Internal audit context: the grant set the actor held at write time. Not a contract.' cluster_id: type: - integer - 'null' description: 'Internal audit context: the cluster that served the write.' trace_id: type: - string - 'null' description: 'Internal audit context: the trace id of the request that wrote the row.' required: - actor_type - actor_sid - team_sid - permissions created_at: type: string updated_at: type: string deleted_at: type: - string - 'null' plaintext_token: type: - string - 'null' required: - sid - team_sid - name - token_prefix - token_last4 - permissions - account_sids - status - expires_at - last_used_at - created_by - created_at - updated_at - deleted_at result: type: object additionalProperties: {} meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - operation - action - item - result - meta CreateApiKeyRequest: type: object description: Request body of `create_api_key`. properties: name: type: string minLength: 1 maxLength: 255 description: Human-readable key name; unique among the team's non-revoked keys. permissions: type: array items: type: string maxLength: 128 description: Unified permission list; must be ⊆ the parent key on delegation. account_sids: type: - array - 'null' items: type: string minLength: 18 maxLength: 18 pattern: ^(ln_ac_|em_ac_) minItems: 1 description: Channel-account slice the key reaches (ln_ac_*/em_ac_*); null/omitted = all team accounts, grantable only by an issuer whose own slice is unrestricted. An empty list is refused (422). expires_at: type: - string - 'null' description: ISO 8601 UTC; omit = now + 3 years; null = perpetual. required: - name - permissions CreateApiKeyResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - create item: type: object properties: sid: type: string team_sid: type: string name: type: string token_prefix: type: string token_last4: type: string permissions: type: array items: type: string account_sids: type: - array - 'null' items: type: string status: type: string enum: - active - revoked - expired expires_at: type: - string - 'null' last_used_at: type: - string - 'null' created_by: type: object properties: actor_type: type: string enum: - user - support - api_key - system - agent actor_sid: type: - string - 'null' team_sid: type: string actor_name: type: - string - 'null' description: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job. oauth_client_sid: type: - string - 'null' description: The acting OAuth client (id_oc_*); null off the OAuth path. reason: type: - string - 'null' description: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise. permissions: type: object additionalProperties: {} description: 'Internal audit context: the grant set the actor held at write time. Not a contract.' cluster_id: type: - integer - 'null' description: 'Internal audit context: the cluster that served the write.' trace_id: type: - string - 'null' description: 'Internal audit context: the trace id of the request that wrote the row.' required: - actor_type - actor_sid - team_sid - permissions created_at: type: string updated_at: type: string deleted_at: type: - string - 'null' plaintext_token: type: - string - 'null' required: - sid - team_sid - name - token_prefix - token_last4 - permissions - account_sids - status - expires_at - last_used_at - created_by - created_at - updated_at - deleted_at already_exists: type: boolean meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - operation - item - already_exists - meta GetApiKeysMetricsRequest: type: object description: Request body of `get_api_keys_metrics`. properties: filter: type: object properties: sid: type: object properties: eq: type: string in: type: array items: type: string additionalProperties: false status: type: object properties: eq: type: string enum: - active - revoked - expired ne: type: string enum: - active - revoked - expired in: type: array items: type: string enum: - active - revoked - expired nin: type: array items: type: string enum: - active - revoked - expired additionalProperties: false name: type: object properties: eq: type: string additionalProperties: false description: Match on the human-readable key name. created_by_actor_sid: type: object properties: eq: type: string in: type: array items: type: string additionalProperties: false description: 'Issuer slice: keys created by this teammate (us_mb_) or parent key (id_ak_); offboarding.' expires_at: type: object properties: gte: type: string lte: type: string gt: type: string lt: type: string is_null: type: boolean additionalProperties: false description: is_null:true = perpetual keys; range = expiring-between. last_used_at: type: object properties: gte: type: string lte: type: string gt: type: string lt: type: string is_null: type: boolean additionalProperties: false description: is_null:true = never used; lt = stale keys. created_at: type: object properties: gte: type: string lte: type: string gt: type: string lt: type: string additionalProperties: false deleted_at: type: object properties: gte: type: string lte: type: string is_null: type: boolean additionalProperties: false description: 'Default scope is { is_null: true } (live rows).' period: type: object properties: from: type: string description: ISO 8601 UTC window start (inclusive). to: type: string description: ISO 8601 UTC window end; must be at or after from. required: - from - to description: Required metrics window [from, to). group_by: type: - string - 'null' enum: - status description: Split the aggregate by key status instead of returning one total. required: - period GetApiKeyResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - get item: type: object properties: sid: type: string team_sid: type: string name: type: string token_prefix: type: string token_last4: type: string permissions: type: array items: type: string account_sids: type: - array - 'null' items: type: string status: type: string enum: - active - revoked - expired expires_at: type: - string - 'null' last_used_at: type: - string - 'null' created_by: type: object properties: actor_type: type: string enum: - user - support - api_key - system - agent actor_sid: type: - string - 'null' team_sid: type: string actor_name: type: - string - 'null' description: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job. oauth_client_sid: type: - string - 'null' description: The acting OAuth client (id_oc_*); null off the OAuth path. reason: type: - string - 'null' description: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise. permissions: type: object additionalProperties: {} description: 'Internal audit context: the grant set the actor held at write time. Not a contract.' cluster_id: type: - integer - 'null' description: 'Internal audit context: the cluster that served the write.' trace_id: type: - string - 'null' description: 'Internal audit context: the trace id of the request that wrote the row.' required: - actor_type - actor_sid - team_sid - permissions created_at: type: string updated_at: type: string deleted_at: type: - string - 'null' plaintext_token: type: - string - 'null' required: - sid - team_sid - name - token_prefix - token_last4 - permissions - account_sids - status - expires_at - last_used_at - created_by - created_at - updated_at - deleted_at included: type: object additionalProperties: {} includes: type: array items: type: string meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - operation - item - included - includes - meta responses: McpServerError: description: MCP error envelope with `error.code` internal_error or service_unavailable. content: application/json: schema: $ref: '#/components/schemas/McpError' McpClientError: description: MCP error envelope. `error.code` is one of validation_failed, nothing_to_update, not_found, relation_not_found, invalid_transition, limit_exceeded, payment_required, duplicate_rejected, conflict, delete_blocked, unauthorized, forbidden, rate_limited, not_implemented. content: application/json: schema: $ref: '#/components/schemas/McpError' securitySchemes: BearerJwt: type: http scheme: bearer bearerFormat: JWT description: Access token issued by gtm.service.id. Its `access_identity` claim carries `team_sid`, `actor_sid` and `actor_type`, and that team scope is authoritative. TeamSid: type: apiKey in: header name: Team-SID description: Team scope for tokens that do not carry one. Ignored when the token already names a team.