openapi: 3.1.0
info:
  title: ThumbGate API
  version: 1.2.0
  description: |
    Production API for feedback capture, schema-validated memory promotion,
    prevention rule generation, and DPO export.
    Bare up/down signals are logged immediately, but the API returns
    clarification_required until one sentence explains what worked or failed.
    When the explanation is specific enough, ThumbGate infers a domain tag if
    the caller omitted manual tags so the feedback can still promote cleanly.
servers:
  - url: https://thumbgate-production.up.railway.app
security:
  - bearerAuth: []
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: API Key
  schemas:
    RubricScore:
      type: object
      required: [criterion, score]
      properties:
        criterion:
          type: string
        score:
          type: number
          minimum: 1
          maximum: 5
        evidence:
          type: string
        judge:
          type: string
    CaptureFeedbackRequest:
      type: object
      required: [signal]
      properties:
        signal:
          type: string
          enum: [up, down, positive, negative]
        context:
          type: string
          description: One-sentence reason describing what worked or failed
        whatWentWrong:
          type: string
        whatToChange:
          type: string
        whatWorked:
          type: string
        rubricScores:
          type: array
          items:
            $ref: '#/components/schemas/RubricScore'
        guardrails:
          type: object
          properties:
            testsPassed:
              type: boolean
            pathSafety:
              type: boolean
            budgetCompliant:
              type: boolean
        tags:
          oneOf:
            - type: array
              items:
                type: string
            - type: string
          description: Optional domain tags. If omitted, ThumbGate infers one from the feedback text before promotion.
        skill:
          type: string
    IntentPlanRequest:
      type: object
      required: [intentId]
      properties:
        intentId:
          type: string
        context:
          type: string
        mcpProfile:
          type: string
        bundleId:
          type: string
        partnerProfile:
          type: string
        delegationMode:
          type: string
          enum: [off, auto, sequential]
        approved:
          type: boolean
        repoPath:
          type: string
    InternalAgentBootstrapRequest:
      type: object
      required: [source]
      properties:
        source:
          type: string
          enum: [github, slack, linear, api, cli]
        repoPath:
          type: string
        prepareSandbox:
          type: boolean
        sandboxRoot:
          type: string
        intentId:
          type: string
        context:
          type: string
        mcpProfile:
          type: string
        partnerProfile:
          type: string
        delegationMode:
          type: string
          enum: [off, auto, sequential]
        approved:
          type: boolean
        trigger:
          type: object
          properties:
            type:
              type: string
            id:
              type: string
            url:
              type: string
            actor:
              type: string
        thread:
          type: object
          properties:
            id:
              type: string
            title:
              type: string
            url:
              type: string
        task:
          type: object
          properties:
            title:
              type: string
            body:
              type: string
            number:
              type: string
            branch:
              type: string
            labels:
              type: array
              items:
                type: string
        comments:
          type: array
          items:
            type: object
            properties:
              author:
                type: string
              text:
                type: string
              timestamp:
                type: string
        messages:
          type: array
          items:
            type: object
            properties:
              author:
                type: string
              text:
                type: string
              timestamp:
                type: string
    HandoffStartRequest:
      type: object
      required: [intentId]
      properties:
        intentId:
          type: string
        context:
          type: string
        mcpProfile:
          type: string
        bundleId:
          type: string
        partnerProfile:
          type: string
        approved:
          type: boolean
        repoPath:
          type: string
        delegateProfile:
          type: string
        plannedChecks:
          type: array
          items:
            type: string
    HandoffCompleteRequest:
      type: object
      required: [handoffId, outcome]
      properties:
        handoffId:
          type: string
        outcome:
          type: string
          enum: [accepted, rejected, aborted]
        resultContext:
          type: string
        attempts:
          type: number
        violationCount:
          type: number
        tokenEstimate:
          type: number
        latencyMs:
          type: number
        summary:
          type: string
    BillingCheckoutRequest:
      type: object
      properties:
        successUrl:
          type: string
          format: uri
        cancelUrl:
          type: string
          format: uri
        customerEmail:
          type: string
          format: email
        installId:
          type: string
        metadata:
          type: object
          additionalProperties:
            type: string
    BillingProvisionRequest:
      type: object
      required: [customerId]
      properties:
        customerId:
          type: string
        installId:
          type: string
    WorkflowSprintIntakeRequest:
      type: object
      required: [email, workflow, owner, blocker, runtime]
      properties:
        email:
          type: string
          format: email
        company:
          type: string
        workflow:
          type: string
        owner:
          type: string
        blocker:
          type: string
        runtime:
          type: string
        note:
          type: string
        acquisitionId:
          type: string
        visitorId:
          type: string
        sessionId:
          type: string
        traceId:
          type: string
        installId:
          type: string
        source:
          type: string
        utmSource:
          type: string
        utmMedium:
          type: string
        utmCampaign:
          type: string
        utmContent:
          type: string
        utmTerm:
          type: string
        community:
          type: string
        postId:
          type: string
        commentId:
          type: string
        campaignVariant:
          type: string
        offerCode:
          type: string
        ctaId:
          type: string
        ctaPlacement:
          type: string
        planId:
          type: string
        page:
          type: string
        landingPath:
          type: string
        referrerHost:
          type: string
        referrer:
          type: string
    WorkflowSprintIntakeResponse:
      type: object
      properties:
        ok:
          type: boolean
        leadId:
          type: string
        status:
          type: string
        offer:
          type: string
        nextStep:
          type: string
        proofPackUrl:
          type: string
          format: uri
        sprintBriefUrl:
          type: string
          format: uri
    WorkflowSprintAdvanceRequest:
      type: object
      required: [leadId, status]
      properties:
        leadId:
          type: string
        status:
          type: string
          enum: [new, qualified, named_pilot, proof_backed_run, paid_team]
        actor:
          type: string
        note:
          type: string
        reviewedBy:
          type: string
        workflowId:
          type: string
        teamId:
          type: string
        proofArtifacts:
          type: array
          items:
            type: string
    WorkflowSprintAdvanceResponse:
      type: object
      properties:
        ok:
          type: boolean
        unchanged:
          type: boolean
        lead:
          type: object
          additionalProperties: true
        workflowRun:
          type: object
          nullable: true
          additionalProperties: true
    FunnelAnalyticsResponse:
      type: object
      properties:
        totalEvents:
          type: integer
        stageCounts:
          type: object
          properties:
            acquisition:
              type: integer
            activation:
              type: integer
            paid:
              type: integer
        eventCounts:
          type: object
          additionalProperties:
            type: integer
        conversionRates:
          type: object
          properties:
            acquisitionToActivation:
              type: number
            activationToPaid:
              type: number
            acquisitionToPaid:
              type: number
        paidProviderEvents:
          type: integer
    BillingSummaryResponse:
      type: object
      properties:
        generatedAt:
          type: string
          format: date-time
        coverage:
          type: object
          properties:
            source:
              type: string
            tracksBookedRevenue:
              type: boolean
            tracksPaidOrders:
              type: boolean
            tracksInvoices:
              type: boolean
            tracksAttribution:
              type: boolean
            providerCoverage:
              type: object
              additionalProperties:
                type: string
        funnel:
          allOf:
            - $ref: '#/components/schemas/FunnelAnalyticsResponse'
            - type: object
              properties:
                uniqueAcquisitionLeads:
                  type: integer
                uniquePaidCustomers:
                  type: integer
                firstPaidAt:
                  type: string
                  nullable: true
                lastPaidAt:
                  type: string
                  nullable: true
                lastPaidEvent:
                  type: object
                  nullable: true
                  properties:
                    timestamp:
                      type: string
                      nullable: true
                    event:
                      type: string
                      nullable: true
                    evidence:
                      type: string
                      nullable: true
                    customerId:
                      type: string
                      nullable: true
                    traceId:
                      type: string
                      nullable: true
        signups:
          type: object
          properties:
            total:
              type: integer
            uniqueLeads:
              type: integer
            bySource:
              type: object
              additionalProperties:
                type: integer
            byCampaign:
              type: object
              additionalProperties:
                type: integer
        pipeline:
          type: object
          properties:
            workflowSprintLeads:
              type: object
              properties:
                total:
                  type: integer
                bySource:
                  type: object
                  additionalProperties:
                    type: integer
            qualifiedWorkflowSprintLeads:
              type: object
              properties:
                total:
                  type: integer
                bySource:
                  type: object
                  additionalProperties:
                    type: integer
        revenue:
          type: object
          properties:
            paidProviderEvents:
              type: integer
            paidOrders:
              type: integer
            paidCustomers:
              type: integer
            bookedRevenueCents:
              type: integer
            bookedRevenueByCurrency:
              type: object
              additionalProperties:
                type: integer
            amountKnownOrders:
              type: integer
            amountUnknownOrders:
              type: integer
            amountKnownCoverageRate:
              type: number
            unreconciledPaidEvents:
              type: integer
            latestPaidAt:
              type: string
              nullable: true
            latestPaidOrder:
              type: object
              nullable: true
              properties:
                timestamp:
                  type: string
                  nullable: true
                provider:
                  type: string
                  nullable: true
                event:
                  type: string
                  nullable: true
                orderId:
                  type: string
                  nullable: true
                customerId:
                  type: string
                  nullable: true
                amountCents:
                  type: integer
                  nullable: true
                currency:
                  type: string
                  nullable: true
                amountKnown:
                  type: boolean
            byProvider:
              type: object
              additionalProperties:
                type: object
                properties:
                  paidOrders:
                    type: integer
                  bookedRevenueCents:
                    type: integer
                  amountKnownOrders:
                    type: integer
                  amountUnknownOrders:
                    type: integer
                  bookedRevenueByCurrency:
                    type: object
                    additionalProperties:
                      type: integer
        attribution:
          type: object
          properties:
            acquisitionBySource:
              type: object
              additionalProperties:
                type: integer
            acquisitionByCampaign:
              type: object
              additionalProperties:
                type: integer
            paidBySource:
              type: object
              additionalProperties:
                type: integer
            paidByCampaign:
              type: object
              additionalProperties:
                type: integer
            bookedRevenueBySourceCents:
              type: object
              additionalProperties:
                type: integer
            bookedRevenueByCampaignCents:
              type: object
              additionalProperties:
                type: integer
            conversionBySource:
              type: object
              additionalProperties:
                type: number
            conversionByCampaign:
              type: object
              additionalProperties:
                type: number
        keys:
          type: object
          properties:
            total:
              type: integer
            active:
              type: integer
            disabled:
              type: integer
            activeCustomers:
              type: integer
            totalUsage:
              type: integer
            bySource:
              type: object
              additionalProperties:
                type: integer
            activeBySource:
              type: object
              additionalProperties:
                type: integer
        customers:
          type: array
          items:
            type: object
            properties:
              customerId:
                type: string
              activeKeys:
                type: integer
              totalKeys:
                type: integer
              usageCount:
                type: integer
              source:
                type: string
              installId:
                type: string
                nullable: true
              createdAt:
                type: string
                nullable: true
              disabledAt:
                type: string
                nullable: true
        trafficMetrics:
          type: object
          properties:
            visitors:
              type: integer
            sessions:
              type: integer
            pageViews:
              type: integer
            ctaClicks:
              type: integer
            checkoutStarts:
              type: integer
            buyerLossFeedback:
              type: integer
            seoLandingViews:
              type: integer
        operatorGeneratedAcquisition:
          type: object
          properties:
            totalEvents:
              type: integer
            uniqueLeads:
              type: integer
            bySource:
              type: object
              additionalProperties:
                type: integer
        dataQuality:
          type: object
          properties:
            telemetryCoverage:
              type: number
            attributionCoverage:
              type: number
            amountKnownCoverage:
              type: number
            unreconciledPaidEvents:
              type: integer
paths:
  /healthz:
    get:
      operationId: healthz
      responses:
        '200':
          description: Service health
        '401':
          description: Unauthorized
  /v1/feedback/capture:
    post:
      operationId: captureFeedback
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CaptureFeedbackRequest'
      responses:
        '200':
          description: Feedback accepted and promoted to memory
        '422':
          description: Feedback logged only; clarification required or promotion rejected
        '401':
          description: Unauthorized
  /v1/feedback/stats:
    get:
      operationId: getFeedbackStats
      responses:
        '200':
          description: Aggregated feedback statistics
        '401':
          description: Unauthorized
  /v1/feedback/infer:
    post:
      operationId: inferLessonFromHistory
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InferLessonRequest'
      responses:
        '200':
          description: Distilled lesson from chat history
        '401':
          description: Unauthorized
  /v1/telemetry/ping:
    post:
      operationId: recordTelemetryPing
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              additionalProperties: true
      responses:
        '204':
          description: Telemetry accepted on a best-effort basis
  /v1/analytics/funnel:
    get:
      operationId: getFunnelAnalytics
      responses:
        '200':
          description: Acquisition/activation/paid funnel metrics from append-only ledger
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/FunnelAnalyticsResponse'
        '401':
          description: Unauthorized
  /v1/analytics/losses:
    get:
      operationId: getLossAnalytics
      parameters:
        - in: query
          name: window
          schema:
            type: string
            enum: [today, 7d, 30d, lifetime]
        - in: query
          name: timezone
          schema:
            type: string
        - in: query
          name: now
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Ranked buyer-loss and revenue-opportunity analysis for the active analytics window
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          description: Unauthorized
  /v1/dashboard:
    get:
      operationId: getDashboard
      parameters:
        - in: query
          name: window
          schema:
            type: string
            enum: [today, 7d, 30d, lifetime]
        - in: query
          name: timezone
          schema:
            type: string
        - in: query
          name: now
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Full ThumbGate dashboard with feedback, telemetry, funnel, and observability analytics
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          description: Unauthorized
  /v1/dashboard/review-state:
    get:
      operationId: getDashboardReviewState
      responses:
        '200':
          description: Persisted dashboard review checkpoint and the current delta since that checkpoint
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          description: Unauthorized
    post:
      operationId: markDashboardReviewed
      responses:
        '200':
          description: Persist and return the current dashboard review checkpoint
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          description: Unauthorized
  /v1/dashboard/render-spec:
    get:
      operationId: getDashboardRenderSpec
      parameters:
        - in: query
          name: view
          schema:
            type: string
            enum: [team-review, incident-review, workflow-rollout]
        - in: query
          name: window
          schema:
            type: string
            enum: [today, 7d, 30d, lifetime]
        - in: query
          name: timezone
          schema:
            type: string
        - in: query
          name: now
          schema:
            type: string
            format: date-time
      responses:
        '200':
          description: Constrained JSON render spec for hosted Team and operations dashboard views
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          description: Invalid dashboard render view or query
        '401':
          description: Unauthorized
  /v1/decisions/evaluate:
    post:
      operationId: evaluateDecision
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                toolName:
                  type: string
                  description: Tool name is optional when provider-native tool call payload is supplied.
                provider:
                  type: string
                model:
                  type: string
                providerToolCall:
                  type: object
                  additionalProperties: true
                toolCall:
                  type: object
                  additionalProperties: true
                toolUse:
                  type: object
                  additionalProperties: true
                content:
                  type: array
                  items:
                    type: object
                    additionalProperties: true
                input:
                  type: object
                  additionalProperties: true
                arguments:
                  type: object
                  additionalProperties: true
                method:
                  type: string
                params:
                  type: object
                  additionalProperties: true
                mcp:
                  type: object
                  additionalProperties: true
                mcpToolCall:
                  type: object
                  additionalProperties: true
                usage:
                  type: object
                  additionalProperties: true
                tokenEstimate:
                  type: number
                costUsd:
                  type: number
                budget:
                  type: object
                  additionalProperties: true
                workflowPattern:
                  type: string
                  enum: [single_action, chaining, routing, parallelization, evaluator-optimizer, agent]
                workflow:
                  type: object
                  additionalProperties: true
                goal:
                  type: string
                tools:
                  type: array
                  items:
                    type: string
                branches:
                  type: array
                  items:
                    type: string
                steps:
                  type: array
                  items:
                    type: string
                routes:
                  type: array
                  items:
                    type: string
                command:
                  type: string
                filePath:
                  type: string
                changedFiles:
                  type: array
                  items:
                    type: string
                repoPath:
                  type: string
                baseBranch:
                  type: string
                requirePrForReleaseSensitive:
                  type: boolean
                requireVersionNotBehindBase:
                  type: boolean
                workflowDispatch:
                  type: object
                  description: Evidence required before running `gh workflow run` or another environment-specific workflow dispatch.
                  properties:
                    environment:
                      type: string
                      description: Requested environment such as dev, staging, beta, or release.
                    workflow:
                      type: string
                      description: Expected workflow file or workflow name.
                    ref:
                      type: string
                      description: Expected branch or ref passed to the workflow dispatch command.
                    sha:
                      type: string
                      description: Expected HEAD SHA to verify before and after dispatch.
                    job:
                      type: string
                      description: Expected job name to verify before reporting the workflow URL.
      responses:
        '200':
          description: Persisted workflow-sentinel recommendation with decision-control metadata and actionId
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          description: Invalid decision evaluation request
        '401':
          description: Unauthorized
  /v1/decisions/outcome:
    post:
      operationId: recordDecisionOutcome
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [actionId, outcome]
              properties:
                actionId:
                  type: string
                outcome:
                  type: string
                actualDecision:
                  type: string
                actor:
                  type: string
                notes:
                  type: string
                latencyMs:
                  type: number
                metadata:
                  type: object
                  additionalProperties: true
      responses:
        '200':
          description: Recorded a decision override, rollback, completion, or block outcome
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '400':
          description: Invalid decision outcome request
        '401':
          description: Unauthorized
  /v1/decisions/metrics:
    get:
      operationId: getDecisionMetrics
      responses:
        '200':
          description: Decision-loop metrics derived from recorded evaluations and outcomes
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          description: Unauthorized
  /v1/settings/status:
    get:
      operationId: getSettingsStatus
      responses:
        '200':
          description: Resolved settings hierarchy with per-field origin metadata for managed, user, project, and local scopes
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        '401':
          description: Unauthorized
  /v1/billing/summary:
    get:
      operationId: getBillingSummary
      responses:
        '200':
          description: Admin-only business summary from the funnel ledger, revenue ledger, and key store
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BillingSummaryResponse'
        '401':
          description: Unauthorized
        '403':
          description: Forbidden
  /v1/intake/workflow-sprint:
    post:
      operationId: submitWorkflowSprintIntake
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkflowSprintIntakeRequest'
      responses:
        '201':
          description: Workflow Hardening Sprint lead accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowSprintIntakeResponse'
        '400':
          description: Invalid sprint intake request
  /v1/intake/workflow-sprint/advance:
    post:
      operationId: advanceWorkflowSprintLead
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkflowSprintAdvanceRequest'
      responses:
        '200':
          description: Workflow Hardening Sprint lead advanced to the next state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WorkflowSprintAdvanceResponse'
        '400':
          description: Invalid sprint advancement request
        '403':
          description: Forbidden
  /v1/intents/catalog:
    get:
      operationId: listIntentCatalog
      parameters:
        - in: query
          name: mcpProfile
          schema:
            type: string
        - in: query
          name: bundleId
          schema:
            type: string
        - in: query
          name: partnerProfile
          schema:
            type: string
      responses:
        '200':
          description: Intent catalog with risk and checkpoint metadata
        '401':
          description: Unauthorized
  /v1/intents/plan:
    post:
      operationId: planIntent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/IntentPlanRequest'
      responses:
        '200':
          description: Policy-scoped intent execution plan
        '400':
          description: Invalid intent request
        '401':
          description: Unauthorized
  /v1/handoffs/start:
    post:
      operationId: startHandoff
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HandoffStartRequest'
      responses:
        '200':
          description: Sequential handoff started
        '400':
          description: Invalid handoff request
        '401':
          description: Unauthorized
  /v1/handoffs/complete:
    post:
      operationId: completeHandoff
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/HandoffCompleteRequest'
      responses:
        '200':
          description: Sequential handoff completed
        '400':
          description: Invalid handoff completion request
        '401':
          description: Unauthorized
  /v1/internal-agent/bootstrap:
    post:
      operationId: bootstrapInternalAgent
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InternalAgentBootstrapRequest'
      responses:
        '200':
          description: Normalized trigger context, recall pack, sandbox, and reviewer-ready execution plan
        '400':
          description: Invalid internal-agent bootstrap request
        '401':
          description: Unauthorized
  /v1/feedback/summary:
    get:
      operationId: getFeedbackSummary
      parameters:
        - in: query
          name: recent
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: Feedback summary text
        '401':
          description: Unauthorized
  /v1/lessons/search:
    get:
      operationId: searchLessons
      parameters:
        - in: query
          name: q
          schema:
            type: string
          description: Search query. Leave empty to list recent lessons.
        - in: query
          name: limit
          schema:
            type: integer
            default: 10
        - in: query
          name: category
          schema:
            type: string
            enum: [error, learning, preference]
        - in: query
          name: tags
          schema:
            type: string
          description: Comma-separated tags that must all be present on a lesson.
      responses:
        '200':
          description: Searchable promoted lessons with linked corrective actions, prevention rules, and auto-promoted checks
        '401':
          description: Unauthorized
  /v1/search:
    get:
      operationId: searchThumbgate
      parameters:
        - in: query
          name: q
          schema:
            type: string
          description: Search query for raw ThumbGate state.
        - in: query
          name: limit
          schema:
            type: integer
            default: 10
        - in: query
          name: source
          schema:
            type: string
            enum: [all, feedback, context, rules]
            default: all
        - in: query
          name: signal
          schema:
            type: string
            enum: [up, down, positive, negative]
      responses:
        '200':
          description: Search results across feedback logs, ContextFS, and prevention rules
        '401':
          description: Unauthorized
    post:
      operationId: searchThumbgatePost
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                q:
                  type: string
                limit:
                  type: integer
                  default: 10
                source:
                  type: string
                  enum: [all, feedback, context, rules]
                  default: all
                signal:
                  type: string
                  enum: [up, down, positive, negative]
      responses:
        '200':
          description: Search results across feedback logs, ContextFS, and prevention rules
        '401':
          description: Unauthorized
  /v1/feedback/rules:
    post:
      operationId: generatePreventionRules
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                minOccurrences:
                  type: integer
                  default: 2
                outputPath:
                  type: string
      responses:
        '200':
          description: Prevention rules generated
        '401':
          description: Unauthorized
  /v1/dpo/export:
    post:
      operationId: exportDpoPairs
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                inputPath:
                  type: string
                memoryLogPath:
                  type: string
                outputPath:
                  type: string
                async:
                  type: boolean
                mode:
                  type: string
                  enum: [sync, async]
                jobId:
                  type: string
      responses:
        '200':
          description: DPO export completed
        '202':
          description: DPO export accepted as a hosted background job
        '401':
          description: Unauthorized
  /v1/documents:
    get:
      operationId: listImportedDocuments
      parameters:
        - in: query
          name: query
          schema:
            type: string
        - in: query
          name: q
          schema:
            type: string
        - in: query
          name: tag
          schema:
            type: string
        - in: query
          name: limit
          schema:
            type: integer
            default: 20
      responses:
        '200':
          description: Imported policy and runbook documents
        '401':
          description: Unauthorized
  /v1/documents/import:
    post:
      operationId: importDocument
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                filePath:
                  type: string
                content:
                  type: string
                title:
                  type: string
                sourceFormat:
                  type: string
                  enum: [markdown, text, yaml, json, html]
                sourceUrl:
                  type: string
                tags:
                  type: array
                  items:
                    type: string
                proposeGates:
                  type: boolean
      responses:
        '201':
          description: Document imported
        '400':
          description: Invalid document import request
        '401':
          description: Unauthorized
  /v1/documents/{documentId}:
    get:
      operationId: getImportedDocument
      parameters:
        - in: path
          name: documentId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Imported document with proposed gates
        '401':
          description: Unauthorized
        '404':
          description: Imported document not found
  /v1/jobs:
    get:
      operationId: listHostedJobs
      parameters:
        - in: query
          name: limit
          schema:
            type: integer
            default: 20
        - in: query
          name: status
          schema:
            type: string
          description: Optional comma-separated list of job statuses to filter.
      responses:
        '200':
          description: Hosted job states
        '401':
          description: Unauthorized
  /v1/jobs/harness:
    post:
      operationId: launchHostedHarness
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [harness]
              properties:
                harness:
                  type: string
                harnessId:
                  type: string
                jobId:
                  type: string
                skill:
                  type: string
                partnerProfile:
                  type: string
                autoImprove:
                  type: boolean
                inputs:
                  type: object
      responses:
        '202':
          description: Hosted harness accepted
        '401':
          description: Unauthorized
  /v1/jobs/{jobId}:
    get:
      operationId: getHostedJob
      parameters:
        - in: path
          name: jobId
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Hosted job state
        '401':
          description: Unauthorized
        '404':
          description: Job not found
  /v1/jobs/{jobId}/control:
    post:
      operationId: controlHostedJob
      parameters:
        - in: path
          name: jobId
          required: true
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [action]
              properties:
                action:
                  type: string
                  enum: [pause, cancel, resume]
                metadata:
                  type: object
      responses:
        '202':
          description: Hosted job control accepted
        '401':
          description: Unauthorized
        '404':
          description: Job not found
        '409':
          description: Job cannot accept the requested control action
  /v1/analytics/databricks/export:
    post:
      operationId: exportDatabricksBundle
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                outputPath:
                  type: string
      responses:
        '200':
          description: Databricks bundle exported
        '401':
          description: Unauthorized
  /v1/context/construct:
    post:
      operationId: constructContextPack
      requestBody:
        required: false
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                maxItems:
                  type: integer
                  default: 8
                maxChars:
                  type: integer
                  default: 6000
                namespaces:
                  type: array
                  items:
                    type: string
                    enum:
                      - raw_history
                      - memory/error
                      - memory/learning
                      - rules
                      - tools
                      - provenance
      responses:
        '200':
          description: Context pack created
        '400':
          description: Invalid namespace selection
        '401':
          description: Unauthorized
  /v1/context/evaluate:
    post:
      operationId: evaluateContextPack
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [packId, outcome]
              properties:
                packId:
                  type: string
                outcome:
                  type: string
                signal:
                  type: string
                notes:
                  type: string
                rubricScores:
                  type: array
                  items:
                    $ref: '#/components/schemas/RubricScore'
                guardrails:
                  type: object
                  properties:
                    testsPassed:
                      type: boolean
                    pathSafety:
                      type: boolean
                    budgetCompliant:
                      type: boolean
      responses:
        '200':
          description: Evaluation recorded
        '400':
          description: Invalid rubric payload
        '401':
          description: Unauthorized
  /v1/context/provenance:
    get:
      operationId: getContextProvenance
      parameters:
        - in: query
          name: limit
          schema:
            type: integer
            default: 50
      responses:
        '200':
          description: Recent provenance events
        '401':
          description: Unauthorized
  /v1/billing/checkout:
    post:
      operationId: createBillingCheckoutSession
      security: []
      requestBody:
        required: false
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillingCheckoutRequest'
      responses:
        '200':
          description: Stripe checkout session created
  /v1/billing/usage:
    get:
      operationId: getBillingUsage
      responses:
        '200':
          description: Usage count for authenticated billing key
        '401':
          description: Unauthorized
  /v1/billing/provision:
    post:
      operationId: provisionBillingKey
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BillingProvisionRequest'
      responses:
        '200':
          description: API key provisioned
        '400':
          description: Missing required customerId
        '401':
          description: Unauthorized
        '403':
          description: Forbidden - requires static THUMBGATE_API_KEY admin token
  /v1/billing/webhook:
    post:
      operationId: stripeBillingWebhook
      security: []
      responses:
        '200':
          description: Webhook accepted
        '400':
          description: Invalid webhook signature or payload
  /v1/billing/github-webhook:
    post:
      operationId: githubMarketplaceWebhook
      security: []
      responses:
        '200':
          description: Webhook accepted
        '400':
          description: Invalid webhook signature or payload
k signature or payload
  /v1/billing/github-webhook:
    post:
      operationId: githubMarketplaceWebhook
      security: []
      responses:
        '200':
          description: Webhook accepted
        '400':
          description: Invalid webhook signature or payload
