> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gtm-api.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Purchase credits

> Top up credits. Creates a Paddle one-time transaction and returns a checkout_url for the human to pay; the credits land AFTER transaction.completed (ASYNC: poll get_credit_balance or await the webhook). CREDITABLE + DESTRUCTIVE: charges the owner's card / opens Paddle checkout; the real gate is the human confirming the amount in the Paddle overlay. On retry the agent MUST reuse the SAME request_id; a fresh key creates a second charge.

Contract:
- MCP tool `purchase_credits`, registry package `mcp.id/credit_transactions`, mount `id.credits`.
- Operation `action`, response envelope `action_async`.
- Flags: dangerous: the MCP layer gates it behind a preview/commit token, and the effect cannot be undone through this API; creditable: the response carries a `credits` block and the call can debit the team ledger.



## OpenAPI

````yaml /api-reference/id/openapi.yaml post /api/credit-transactions/purchase
openapi: 3.0.3
info:
  title: 'GTM API public contract: gtm.service.id'
  description: >-
    Identity, access and money: users, teams and members, API keys, OAuth
    clients and authorizations, billing products, subscriptions, transactions
    and payment methods, the credit ledger, notifications, TLS certificates,
    observability and support requests.


    GENERATED. This document is projected from the Zod MCP tool registry in
    `product/mcp/gtm.mcp` (one tool per public endpoint, 1:1). Do not edit it by
    hand; edit the tool definition and regenerate with `pnpm openapi:public`.


    Surface: the public `/api` contract of `gtm.service.id`, 77 operations.
    Internal (`/internal`) and health endpoints are deliberately absent; the
    code-faithful spec that documents those lives in
    `product/openapi/gtm.openapi.tech`.


    Conventions:

    - Auth is a bearer JWT, optionally narrowed by the `Team-SID` header.

    - Every success body is an MCP envelope: `success: true` plus one typed
    `operation` shape (`search`, `get`, `create`, `update`, `delete`, `metrics`,
    `group_by`, `action`), and a `meta` block with `trace_id` for support.

    - Every failure is the same `McpError` envelope with a code from a fixed
    16-code taxonomy, so a client maps errors once.

    - Lists page with `page_size` (0 to 500, default 50) plus an opaque forward
    `cursor`; `page_size: 0` returns counts only.

    - On `GET` and `DELETE`, object-valued query parameters (`filter`, `sort`)
    travel as JSON text and array-valued ones repeat as `name[]=value`.

    - The MCP-only `_meta` field (usage analytics) never reaches the backend and
    is not part of this contract.
  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
  - url: http://localhost:8021
    description: Local Docker (gtm_id_nginx_dev)
security:
  - BearerJwt: []
    TeamSid: []
tags:
  - name: account_shares
    description: Registry package `mcp.id/account_shares`, served on MCP mount `id.access`.
  - name: api_keys
    description: Registry package `mcp.id/api_keys`, served on MCP mount `id.access`.
  - name: billing_payment_methods
    description: >-
      Registry package `mcp.id/billing_payment_methods`, served on MCP mount
      `id.billing`.
  - name: billing_products
    description: >-
      Registry package `mcp.id/billing_products`, served on MCP mount
      `id.billing`.
  - name: billing_subscriptions
    description: >-
      Registry package `mcp.id/billing_subscriptions`, served on MCP mount
      `id.billing`.
  - name: billing_transactions
    description: >-
      Registry package `mcp.id/billing_transactions`, served on MCP mount
      `id.billing`.
  - name: credit_transactions
    description: >-
      Registry package `mcp.id/credit_transactions`, served on MCP mount
      `id.credits`.
  - name: notifications
    description: >-
      Registry package `mcp.id/notifications`, served on MCP mount
      `id.platform`.
  - name: oauth_authorizations
    description: >-
      Registry package `mcp.id/oauth_authorizations`, served on MCP mount
      `id.access`.
  - name: oauth_clients
    description: Registry package `mcp.id/oauth_clients`, served on MCP mount `id.access`.
  - name: observability_requests
    description: >-
      Registry package `mcp.id/observability_requests`, served on MCP mount
      `id.platform`.
  - name: sessions
    description: Registry package `mcp.id/sessions`, served on MCP mount `id.identity`.
  - name: ssl_certificates
    description: >-
      Registry package `mcp.id/ssl_certificates`, served on MCP mount
      `id.platform`.
  - name: support_requests
    description: >-
      Registry package `mcp.id/support_requests`, served on MCP mount
      `id.platform`.
  - name: team_members
    description: Registry package `mcp.id/team_members`, served on MCP mount `id.identity`.
  - name: teams
    description: Registry package `mcp.id/teams`, served on MCP mount `id.identity`.
  - name: users
    description: Registry package `mcp.id/users`, served on MCP mount `id.identity`.
paths:
  /api/credit-transactions/purchase:
    post:
      tags:
        - credit_transactions
      summary: Purchase credits
      description: >-
        Top up credits. Creates a Paddle one-time transaction and returns a
        checkout_url for the human to pay; the credits land AFTER
        transaction.completed (ASYNC: poll get_credit_balance or await the
        webhook). CREDITABLE + DESTRUCTIVE: charges the owner's card / opens
        Paddle checkout; the real gate is the human confirming the amount in the
        Paddle overlay. On retry the agent MUST reuse the SAME request_id; a
        fresh key creates a second charge.


        Contract:

        - MCP tool `purchase_credits`, registry package
        `mcp.id/credit_transactions`, mount `id.credits`.

        - Operation `action`, response envelope `action_async`.

        - Flags: dangerous: the MCP layer gates it behind a preview/commit
        token, and the effect cannot be undone through this API; creditable: the
        response carries a `credits` block and the call can debit the team
        ledger.
      operationId: purchase_credits
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PurchaseCreditsRequest'
      responses:
        '200':
          description: '`action_async` success envelope.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PurchaseCreditsResponse'
        4XX:
          $ref: '#/components/responses/McpClientError'
        5XX:
          $ref: '#/components/responses/McpServerError'
components:
  schemas:
    PurchaseCreditsRequest:
      type: object
      description: Request body of `purchase_credits`.
      properties:
        kind:
          type: string
          enum:
            - enrichment
          description: 'Consumable family: MVP "enrichment".'
        amount:
          type: integer
          minimum: 1
          description: Credits to buy.
        request_id:
          type: string
          maxLength: 64
          description: >-
            Idempotency key; MUST be stable across retries. A new key = a second
            charge.
      required:
        - kind
        - amount
        - request_id
    PurchaseCreditsResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
        operation:
          type: string
          enum:
            - action
        action:
          type: string
        async:
          type: boolean
          enum:
            - true
        item:
          type: object
          nullable: true
          properties:
            sid:
              type: string
            team_sid:
              type: string
            kind:
              type: string
              enum:
                - enrichment
            type:
              type: string
              enum:
                - allocation
                - debit
                - refund
                - expiry
            status:
              type: string
              enum:
                - pending
                - confirmed
                - released
                - expired
            amount:
              type: number
            operation:
              type: string
              nullable: true
            reference_sid:
              type: string
              nullable: true
            request_id:
              type: string
              nullable: true
            expires_at:
              type: string
              nullable: true
            metadata:
              type: object
              nullable: true
              properties:
                account_sid:
                  type: string
                  nullable: true
                lot_breakdown:
                  type: array
                  nullable: true
                  items:
                    type: object
                    properties:
                      lot_sid:
                        type: string
                      amount:
                        type: number
                    required:
                      - lot_sid
                      - amount
                purchase:
                  type: boolean
                  nullable: true
              required:
                - account_sid
                - lot_breakdown
                - purchase
            confirmed_at:
              type: string
              nullable: true
            released_at:
              type: string
              nullable: true
            created_at:
              type: string
            updated_at:
              type: string
          required:
            - sid
            - team_sid
            - kind
            - type
            - status
            - amount
            - operation
            - reference_sid
            - request_id
            - expires_at
            - metadata
            - confirmed_at
            - released_at
            - created_at
            - updated_at
        pending:
          type: array
          items:
            type: object
            properties:
              activity_log_sid:
                type: string
              expected_completion_seconds:
                type: integer
                minimum: 0
              webhook_events:
                type: array
                items:
                  type: string
            required:
              - expected_completion_seconds
              - webhook_events
        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.
            debug_url:
              type: string
              description: Deep link to the post-call analysis UI.
          required:
            - trace_id
            - span_id
            - timestamp
            - duration_ms
            - debug_url
        credits:
          type: object
          properties:
            charged:
              type: integer
              minimum: 0
              description: Credits debited for THIS call (0 on own-account / cache hit).
            reason:
              type: string
              nullable: true
              enum:
                - infra_pool
                - limit_fallback
            executed_on:
              type: string
              enum:
                - own_account
                - infra_pool
            balance_after:
              type: integer
              nullable: true
              minimum: 0
              description: >-
                Team balance after the debit; null when the ledger was
                untouched.
          required:
            - charged
            - reason
            - executed_on
            - balance_after
      required:
        - success
        - operation
        - action
        - async
        - item
        - pending
        - result
        - meta
    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:
                  anyOf:
                    - type: string
                    - 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
                    nullable: true
                  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.
            debug_url:
              type: string
              description: Deep link to the post-call analysis UI.
          required:
            - trace_id
            - span_id
            - timestamp
            - duration_ms
            - debug_url
      required:
        - success
        - error
  responses:
    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'
    McpServerError:
      description: >-
        MCP error envelope with `error.code` internal_error or
        service_unavailable.
      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.

````