openapi: 3.2.0 info: title: 'GTM API public contract: gtm.service.id Users 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: Users description: Registry package `mcp.id/users`, served on MCP mount `id.identity`. paths: /api/users/current: get: operationId: get_current_user summary: Get current user description: 'Return the authenticated user''s own profile: the JWT subject, self only (no {sid} form). include[]=default_team hydrates the working team; include[]=accessible_teams returns the owner + active-membership union (workspace switcher / OAuth consent multiselect). Reads email, name, timezone, default_team_sid. Needs a credential with a person behind it (an app session or an OAuth connector). An API key authenticates as itself, not as a user, so on a key this answers 403 with context.reason=not_a_user_actor and no permission changes that. Contract: - MCP tool `get_current_user`, registry package `mcp.id/users`, mount `id.identity`. - Operation `get`, response envelope `get`. - Flags: read only.' tags: - Users parameters: - name: include[] in: query required: false description: 'Relations to eager-load: default_team, accessible_teams.' style: form explode: true schema: type: array items: type: string enum: - default_team - accessible_teams description: 'Relations to eager-load: default_team, accessible_teams.' responses: '200': description: '`get` success envelope.' content: application/json: schema: $ref: '#/components/schemas/GetCurrentUserResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: get_current_user x-gtm-mcp-mount: id.identity x-gtm-entity: users 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_current_user summary: Update current user description: 'Patch the authenticated user''s own profile: first_name / last_name / avatar_url / phone / timezone / country / config only. email (change-email flow), password (change-password flow), auth_provider, email_status and all sids are rejected if sent. At least one field required. config merges key-by-key. Same subject as get_current_user: an API key has no user to patch and answers 403 with context.reason=not_a_user_actor. Contract: - MCP tool `update_current_user`, registry package `mcp.id/users`, mount `id.identity`. - Operation `update`, response envelope `update`. - Flags: none.' tags: - Users requestBody: required: false content: application/json: schema: $ref: '#/components/schemas/UpdateCurrentUserRequest' responses: '200': description: '`update` success envelope.' content: application/json: schema: $ref: '#/components/schemas/UpdateCurrentUserResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: update_current_user x-gtm-mcp-mount: id.identity x-gtm-entity: users 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 components: schemas: 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 UpdateCurrentUserResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - update item: type: object properties: sid: type: string default_team_sid: type: - string - 'null' email: type: string email_status: type: string enum: - unverified - verified auth_provider: type: string enum: - password - google first_name: type: string last_name: type: - string - 'null' avatar_url: type: - string - 'null' phone: type: - string - 'null' timezone: type: - string - 'null' country: type: - string - 'null' config: type: - object - 'null' properties: latest_team_sid: type: - string - 'null' description: Which workspace to open on load (ts_tm_…); NOT default_team_sid. setup_completed: type: boolean description: The post-signup wizard is finished (or its last step was skipped). setup_step: type: - string - 'null' enum: - verify - questions - workspace - linkedin - call description: Resume point inside the wizard; null = not started. setup_call_step: type: - boolean - 'null' description: 'Read-only. Whether this user''s wizard includes step 04 (intro call): null = not scored yet, so it is offered. Server-computed from the step 02 sender bracket; silently dropped if sent to update.' onboarding_completed: type: boolean onboarding_steps: type: array items: type: string locale: type: - string - 'null' maxLength: 8 utm: type: - object - 'null' additionalProperties: type: string created_at: type: string updated_at: type: string erasure_requested_at: type: - string - 'null' erased_at: type: - string - 'null' deleted_at: type: - string - 'null' required: - sid - default_team_sid - email - email_status - auth_provider - first_name - last_name - avatar_url - phone - timezone - country - config - utm - created_at - updated_at - erasure_requested_at - erased_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 GetCurrentUserResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - get item: type: object properties: sid: type: string default_team_sid: type: - string - 'null' email: type: string email_status: type: string enum: - unverified - verified auth_provider: type: string enum: - password - google first_name: type: string last_name: type: - string - 'null' avatar_url: type: - string - 'null' phone: type: - string - 'null' timezone: type: - string - 'null' country: type: - string - 'null' config: type: - object - 'null' properties: latest_team_sid: type: - string - 'null' description: Which workspace to open on load (ts_tm_…); NOT default_team_sid. setup_completed: type: boolean description: The post-signup wizard is finished (or its last step was skipped). setup_step: type: - string - 'null' enum: - verify - questions - workspace - linkedin - call description: Resume point inside the wizard; null = not started. setup_call_step: type: - boolean - 'null' description: 'Read-only. Whether this user''s wizard includes step 04 (intro call): null = not scored yet, so it is offered. Server-computed from the step 02 sender bracket; silently dropped if sent to update.' onboarding_completed: type: boolean onboarding_steps: type: array items: type: string locale: type: - string - 'null' maxLength: 8 utm: type: - object - 'null' additionalProperties: type: string created_at: type: string updated_at: type: string erasure_requested_at: type: - string - 'null' erased_at: type: - string - 'null' deleted_at: type: - string - 'null' required: - sid - default_team_sid - email - email_status - auth_provider - first_name - last_name - avatar_url - phone - timezone - country - config - utm - created_at - updated_at - erasure_requested_at - erased_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 UpdateCurrentUserRequest: type: object description: Request body of `update_current_user`. properties: first_name: type: string minLength: 1 maxLength: 100 last_name: type: - string - 'null' maxLength: 100 avatar_url: type: - string - 'null' maxLength: 1024 phone: type: - string - 'null' maxLength: 32 timezone: type: - string - 'null' description: IANA tz, e.g. "Europe/Riga". country: type: - string - 'null' minLength: 2 maxLength: 2 description: ISO 3166-1 alpha-2. config: type: object properties: latest_team_sid: type: - string - 'null' description: Which workspace to open on load (ts_tm_…); NOT default_team_sid. setup_completed: type: boolean description: The post-signup wizard is finished (or its last step was skipped). setup_step: type: - string - 'null' enum: - verify - questions - workspace - linkedin - call description: Resume point inside the wizard; null = not started. onboarding_completed: type: boolean onboarding_steps: type: array items: type: string locale: type: - string - 'null' maxLength: 8 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.