openapi: 3.1.0
info:
  title: DriftGuard Hosted API
  version: 0.9.16
  description: |
    Customer-plane HTTP API for watches, drift events, and command-center bundles.

    **Coverage:** watches, drift, and command-center families (`49` paths).
    Additional families (billing, FuseGuard ingest, org admin) are documented in follow-up releases.

    Errors return legacy `error` plus additive `error_v2` — see [/docs/errors](/docs/errors).
  contact:
    name: DriftGuard
    url: https://driftguard.org
servers:
  - url: https://driftguard.org
    description: Production
security:
  - ApiKeyAuth: []
  - TrialSession: []
paths:
  /api/command-center/agent-consumers:
    get:
      operationId: get_command_center_agent_consumers
      summary: "GET /api/command-center/agent-consumers"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/attention:
    get:
      operationId: get_command_center_attention
      summary: "GET /api/command-center/attention"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/drift-issues:
    get:
      operationId: get_command_center_drift_issues
      summary: "GET /api/command-center/drift-issues"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/fingerprint-timeline:
    get:
      operationId: get_command_center_fingerprint_timeline
      summary: "GET /api/command-center/fingerprint-timeline"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/fleet-table:
    get:
      operationId: get_command_center_fleet_table
      summary: "GET /api/command-center/fleet-table"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/home:
    get:
      operationId: get_command_center_home
      summary: "Command home bundle (posture, actions, pulse)"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/overview:
    get:
      operationId: get_command_center_overview
      summary: "GET /api/command-center/overview"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/recommendations:
    get:
      operationId: get_command_center_recommendations
      summary: "GET /api/command-center/recommendations"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/scorecards:
    get:
      operationId: get_command_center_scorecards
      summary: "GET /api/command-center/scorecards"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/command-center/slos:
    get:
      operationId: get_command_center_slos
      summary: "GET /api/command-center/slos"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift:
    get:
      operationId: get_drift
      summary: "List drift events"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/events/{eventId}:
    get:
      operationId: get_drift_events_by
      summary: "GET /api/drift/events/{eventId}"
      parameters:
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/events/{eventId}/acknowledge:
    post:
      operationId: post_drift_events_by_acknowledge
      summary: "POST /api/drift/events/{eventId}/acknowledge"
      parameters:
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/events/{eventId}/compatibility-receipt:
    get:
      operationId: get_drift_events_by_compatibility_receipt
      summary: "GET /api/drift/events/{eventId}/compatibility-receipt"
      parameters:
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/events/{eventId}/diff:
    get:
      operationId: get_drift_events_by_diff
      summary: "GET /api/drift/events/{eventId}/diff"
      parameters:
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/events/{eventId}/lockfile-patch:
    get:
      operationId: get_drift_events_by_lockfile_patch
      summary: "GET /api/drift/events/{eventId}/lockfile-patch"
      parameters:
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/events/{eventId}/promote-baseline:
    post:
      operationId: post_drift_events_by_promote_baseline
      summary: "POST /api/drift/events/{eventId}/promote-baseline"
      parameters:
        - name: eventId
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/explain:
    post:
      operationId: post_drift_explain
      summary: "POST /api/drift/explain"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/export:
    get:
      operationId: get_drift_export
      summary: "GET /api/drift/export"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/export/incident-packet:
    get:
      operationId: get_drift_export_incident_packet
      summary: "GET /api/drift/export/incident-packet"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/receipts:
    get:
      operationId: get_drift_receipts
      summary: "GET /api/drift/receipts"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/drift/summary:
    get:
      operationId: get_drift_summary
      summary: "GET /api/drift/summary"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches:
    get:
      operationId: get_watches
      summary: "List watches visible to the caller"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
    post:
      operationId: post_watches
      summary: "Create a watch"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/fleet:
    get:
      operationId: get_watches_fleet
      summary: "GET /api/watches/fleet"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/from-template:
    post:
      operationId: post_watches_from_template
      summary: "POST /api/watches/from-template"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/import-ci:
    post:
      operationId: post_watches_import_ci
      summary: "POST /api/watches/import-ci"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/suggest:
    post:
      operationId: post_watches_suggest
      summary: "POST /api/watches/suggest"
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}:
    delete:
      operationId: delete_watches_by
      summary: "Delete a watch"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
    patch:
      operationId: patch_watches_by
      summary: "Update watch settings"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/affected-agents:
    get:
      operationId: get_watches_by_affected_agents
      summary: "GET /api/watches/{id}/affected-agents"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/analytics:
    get:
      operationId: get_watches_by_analytics
      summary: "GET /api/watches/{id}/analytics"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/check:
    post:
      operationId: post_watches_by_check
      summary: "POST /api/watches/{id}/check"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/drift:
    get:
      operationId: get_watches_by_drift
      summary: "GET /api/watches/{id}/drift"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/endpoints/events:
    get:
      operationId: get_watches_by_endpoints_events
      summary: "GET /api/watches/{id}/endpoints/events"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/endpoints/profile:
    get:
      operationId: get_watches_by_endpoints_profile
      summary: "GET /api/watches/{id}/endpoints/profile"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/incident/ack:
    post:
      operationId: post_watches_by_incident_ack
      summary: "POST /api/watches/{id}/incident/ack"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/incident/resolve:
    post:
      operationId: post_watches_by_incident_resolve
      summary: "POST /api/watches/{id}/incident/resolve"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/inventory:
    get:
      operationId: get_watches_by_inventory
      summary: "GET /api/watches/{id}/inventory"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/inventory/suggestions:
    get:
      operationId: get_watches_by_inventory_suggestions
      summary: "GET /api/watches/{id}/inventory/suggestions"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/mcp-invoke-probe:
    post:
      operationId: post_watches_by_mcp_invoke_probe
      summary: "POST /api/watches/{id}/mcp-invoke-probe"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/monitored-endpoints:
    patch:
      operationId: patch_watches_by_monitored_endpoints
      summary: "PATCH /api/watches/{id}/monitored-endpoints"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/publisher-lockfile:
    get:
      operationId: get_watches_by_publisher_lockfile
      summary: "GET /api/watches/{id}/publisher-lockfile"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/remediation-approval:
    get:
      operationId: get_watches_by_remediation_approval
      summary: "GET /api/watches/{id}/remediation-approval"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/remediation-runs:
    get:
      operationId: get_watches_by_remediation_runs
      summary: "GET /api/watches/{id}/remediation-runs"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/schema-history:
    get:
      operationId: get_watches_by_schema_history
      summary: "GET /api/watches/{id}/schema-history"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/status:
    get:
      operationId: get_watches_by_status
      summary: "GET /api/watches/{id}/status"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/test-alert:
    post:
      operationId: post_watches_by_test_alert
      summary: "POST /api/watches/{id}/test-alert"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/tools/events:
    get:
      operationId: get_watches_by_tools_events
      summary: "GET /api/watches/{id}/tools/events"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/tools/profile:
    get:
      operationId: get_watches_by_tools_profile
      summary: "GET /api/watches/{id}/tools/profile"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
  /api/watches/{id}/trigger_remediation:
    post:
      operationId: post_watches_by_trigger_remediation
      summary: "POST /api/watches/{id}/trigger_remediation"
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
      security:
        - ApiKeyAuth: []
        - TrialSession: []
      responses:
        '200':
          description: Success
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      description: Pro/Team API key from /activate
    TrialSession:
      type: apiKey
      in: header
      name: X-DriftGuard-Trial
      description: Trial session from /start
  schemas:
    ApiErrorV2:
      type: object
      required: [code, message, request_id, docs_url]
      properties:
        code:
          type: string
          enum: [not_found, unauthorized, payment_required, validation_failed, rate_limited, conflict, internal]
        message:
          type: string
        request_id:
          type: string
          format: uuid
        docs_url:
          type: string
          format: uri
    ApiErrorResponse:
      type: object
      required: [error, error_v2]
      properties:
        error:
          type: string
          description: Legacy human-readable error (stable)
        error_v2:
          $ref: '#/components/schemas/ApiErrorV2'
  responses:
    Unauthorized:
      description: Missing or invalid credentials
      headers:
        X-Request-Id:
          schema: { type: string, format: uuid }
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
    PaymentRequired:
      description: Plan upgrade required
      headers:
        X-Request-Id:
          schema: { type: string, format: uuid }
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
    NotFound:
      description: Resource not found
      headers:
        X-Request-Id:
          schema: { type: string, format: uuid }
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiErrorResponse'
