{
  "openapi": "3.1.0",
  "info": {
    "title": "DriftGuard Hosted Watchtower API",
    "version": "0.6.0",
    "description": "External dependency drift monitoring for REST/OpenAPI and MCP servers."
  },
  "servers": [
    { "url": "https://driftguard.org" },
    { "url": "https://developers.driftguard.org", "description": "Developer portal (docs only)" }
  ],
  "paths": {
    "/health": {
      "get": {
        "summary": "Service health",
        "responses": { "200": { "description": "OK" } }
      }
    },
    "/api/watches": {
      "get": {
        "summary": "List watches",
        "parameters": [
          { "name": "Authorization", "in": "header", "schema": { "type": "string" } },
          { "name": "X-DriftGuard-Trial", "in": "header", "schema": { "type": "string" } }
        ],
        "responses": { "200": { "description": "Watch list" } }
      },
      "post": {
        "summary": "Create watch",
        "responses": { "201": { "description": "Created" } }
      }
    },
    "/api/watches/suggest": {
      "post": {
        "summary": "Suggest watches from URLs or mcp.json",
        "responses": { "200": { "description": "Suggestions" } }
      }
    },
    "/api/portfolio/overview": {
      "get": {
        "summary": "Portfolio health, analytics, alert stats, dashboard templates",
        "responses": { "200": { "description": "Overview" } }
      }
    },
    "/api/alerts/stats": {
      "get": { "summary": "Alert delivery statistics", "responses": { "200": { "description": "Stats" } } }
    },
    "/api/coverage/assert": {
      "post": {
        "summary": "Assert all suggested dependencies are watched (Pro+ API key)",
        "responses": { "200": { "description": "Full coverage" }, "422": { "description": "Missing watches" } }
      }
    },
    "/api/repo/scan": {
      "post": { "summary": "Scan repo file contents for watch candidates", "responses": { "200": { "description": "Scan result" } } }
    },
    "/api/drift/explain": {
      "post": { "summary": "Explain drift changes with agentAction hints", "responses": { "200": { "description": "Explanation" } } }
    },
    "/api/drift/export": {
      "get": {
        "summary": "Export drift history",
        "parameters": [
          { "name": "format", "in": "query", "schema": { "type": "string", "enum": ["json", "csv", "audit"] } }
        ],
        "responses": { "200": { "description": "Export" } }
      }
    },
    "/api/preflight": {
      "post": {
        "summary": "Orchestrator preflight gate before agent run",
        "responses": { "200": { "description": "Allowed" }, "409": { "description": "Blocked by policy" } }
      }
    },
    "/api/portfolio/compass": {
      "get": {
        "summary": "Portfolio Compass — coverage map and drift hotspots",
        "responses": { "200": { "description": "Compass data" } }
      }
    },
    "/api/portfolio/status": {
      "get": {
        "summary": "Per-watch drift_status summary",
        "responses": { "200": { "description": "Status list" } }
      }
    },
    "/api/coverage/preview": {
      "post": {
        "summary": "Preview coverage gaps (no key, rate-limited)",
        "responses": { "200": { "description": "Preview result" } }
      }
    },
    "/api/public/agent-config": {
      "get": {
        "summary": "MCP install metadata for agents",
        "responses": { "200": { "description": "Agent config JSON" } }
      }
    },
    "/api/funnel/events": {
      "post": {
        "summary": "First-party funnel micro-events",
        "responses": { "202": { "description": "Accepted" } }
      }
    },
    "/api/validate": {
      "post": {
        "summary": "Runtime ingress validate — payload vs pinned consumer profile",
        "description": "Validate JSON payloads against inline consumer profiles before automation writes. Metered per plan; payloads are not stored.",
        "parameters": [
          { "name": "Authorization", "in": "header", "schema": { "type": "string" }, "description": "Bearer dg_… API key" },
          { "name": "X-DriftGuard-Trial", "in": "header", "schema": { "type": "string" }, "description": "Trial session (500 validations/month)" },
          { "name": "X-DriftGuard-Correlation-Id", "in": "header", "schema": { "type": "string" } },
          { "name": "X-DriftGuard-Source", "in": "header", "schema": { "type": "string", "description": "e.g. n8n, curl" } }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["payload"],
                "properties": {
                  "payload": { "type": "object" },
                  "profile": { "type": "object", "description": "Consumer profile (max 64KB)" },
                  "profileId": { "type": "string", "description": "Hosted profile registry id" },
                  "options": {
                    "type": "object",
                    "properties": {
                      "profileMode": { "type": "string", "enum": ["cli", "hosted"] },
                      "mode": { "type": "string", "enum": ["block", "warn", "quarantine"] },
                      "webhookUrl": { "type": "string", "format": "uri", "description": "HTTPS quarantine webhook" }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": { "description": "Valid payload or warn mode with ok:false" },
          "401": { "description": "Missing or invalid API key" },
          "402": { "description": "Monthly validation quota exceeded" },
          "403": { "description": "Free tier without API access" },
          "422": { "description": "Validation failed (block mode)" },
          "429": { "description": "Burst rate limit exceeded" },
          "503": { "description": "Validate API disabled" }
        }
      }
    },
    "/v1/fuseguard/trips": {
      "post": {
        "summary": "Ingest FuseGuard trip event",
        "responses": { "201": { "description": "Recorded" } }
      }
    },
    "/v1/fuseguard/snapshots": {
      "post": {
        "summary": "On-demand FuseGuard snapshot",
        "responses": { "201": { "description": "Snapshot created" } }
      }
    }
  }
}
