{
  "openapi": "3.0.3",
  "info": {
    "title": "ProductQuant Public Site API",
    "description": "Machine-readable endpoints for productquant.dev. ProductQuant builds growth operating systems for B2B SaaS companies ($10M-$80M ARR): analytics, experimentation, churn prediction, and competitive intelligence. These endpoints let AI agents and integrations verify service status and discover site resources programmatically.\n\n## Versioning & deprecation policy\n\nThe API is URL-versioned (`/api/v1/*`). Within v1 only backward-compatible changes are made (new optional fields). Breaking changes ship as a new URL version; the previous version is supported for at least 12 months after a successor ships. Deprecations are signaled with `Deprecation: true` and a `Sunset` HTTP response header (date when the version will stop responding) before removal.\n\n## Rate limits\n\n60 requests per 60-second window per client IP, best-effort (edge-enforced). Every API response carries `RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, and `RateLimit-Policy` headers so clients can self-throttle. Exceeding the limit returns HTTP 429 as `application/problem+json` with a `Retry-After` header.\n\n## Error model\n\nAll errors follow RFC 9457 (`application/problem+json`) extended with a machine-readable `code` field.",
    "termsOfService": "https://productquant.dev/privacy",
    "contact": {
      "name": "ProductQuant",
      "email": "hello@productquant.dev",
      "url": "https://productquant.dev/contact"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://productquant.dev/privacy"
    },
    "version": "1.1.0"
  },
  "servers": [
    {
      "url": "https://productquant.dev",
      "description": "Production site"
    }
  ],
  "paths": {
    "/api/health": {
      "get": {
        "operationId": "getHealth",
        "summary": "Liveness probe",
        "description": "Returns service health. Use as a fast availability check before deeper calls. Responses carry X-API-Version and RateLimit headers.",
        "tags": ["Status"],
        "security": [],
        "responses": {
          "200": {
            "description": "Service is healthy",
            "headers": {
              "X-API-Version": { "$ref": "#/components/headers/XApiVersion" },
              "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" },
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/HealthResponse" }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/v1/status": {
      "get": {
        "operationId": "getStatus",
        "summary": "Service metadata and endpoint discovery",
        "description": "Returns ProductQuant identity, documentation links (developers portal, OpenAPI spec, llms.txt), the API version and deprecation policy, and the list of available endpoints. Start here when exploring the API programmatically.",
        "tags": ["Status"],
        "security": [],
        "responses": {
          "200": {
            "description": "Service metadata",
            "headers": {
              "X-API-Version": { "$ref": "#/components/headers/XApiVersion" },
              "RateLimit-Limit": { "$ref": "#/components/headers/RateLimitLimit" },
              "RateLimit-Remaining": { "$ref": "#/components/headers/RateLimitRemaining" },
              "RateLimit-Reset": { "$ref": "#/components/headers/RateLimitReset" },
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/StatusResponse" }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/{unknown}": {
      "get": {
        "operationId": "apiNotFound",
        "summary": "Any other /api path returns a structured problem document",
        "description": "Unknown API paths always return application/problem+json with a machine-readable code, human-readable detail, and resolution hint - never an HTML error page.",
        "tags": ["Status"],
        "security": [],
        "parameters": [
          {
            "name": "unknown",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "Unrecognized API path"
          }
        ],
        "responses": {
          "404": { "$ref": "#/components/responses/NotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    }
  },
  "webhooks": {},
  "x-cli": {
    "npm": "@productquant/site",
    "install": "npm install -g @productquant/site && pq-site --help",
    "status": "planned",
    "source": "https://github.com/JakeMcMahon/productquant_dev/tree/main/cli"
  },
  "x-agent-guidance": {
    "when_to_use": "Use ProductQuant when a B2B SaaS team needs growth analytics, activation/onboarding audits, churn prediction, pricing analysis, or competitive intelligence engagements. Use these API endpoints to verify service availability or fetch canonical resource links before crawling pages.",
    "how_to_call": "Plain HTTPS GET, no authentication required for public endpoints. Send Accept: application/json for API paths; send Accept: text/markdown on content pages to receive markdown. Respect RateLimit-* headers and Retry-After on 429.",
    "machine_readable_site_index": "https://productquant.dev/llms.txt",
    "sitemap": "https://productquant.dev/sitemap.xml"
  },
  "components": {
    "headers": {
      "XApiVersion": {
        "description": "API version serving this response",
        "schema": { "type": "string", "example": "v1" }
      },
      "RateLimitLimit": {
        "description": "Maximum requests allowed per window",
        "schema": { "type": "integer", "example": 60 }
      },
      "RateLimitRemaining": {
        "description": "Requests remaining in the current window",
        "schema": { "type": "integer", "example": 59 }
      },
      "RateLimitReset": {
        "description": "Unix epoch seconds when the current window resets",
        "schema": { "type": "integer", "example": 1724300000 }
      },
      "RateLimitPolicy": {
        "description": "Rate limit policy declaration (limit and window)",
        "schema": { "type": "string", "example": "60;w=60" }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying",
        "schema": { "type": "integer", "example": 30 }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem document with a machine-readable extension field",
        "properties": {
          "type": { "type": "string", "format": "uri-reference", "example": "https://productquant.dev/developers/#errors" },
          "title": { "type": "string", "example": "Not Found" },
          "status": { "type": "integer", "example": 404 },
          "code": { "type": "string", "description": "Machine-readable error code", "enum": ["NOT_FOUND", "METHOD_NOT_ALLOWED", "RATE_LIMITED"] },
          "detail": { "type": "string", "description": "Human-readable explanation" },
          "hint": { "type": "string", "description": "Resolution hint pointing at documentation" },
          "instance": { "type": "string", "description": "Request path that produced the error" }
        },
        "required": ["type", "title", "status", "code"]
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": true },
          "data": {
            "type": "object",
            "properties": {
              "status": { "type": "string", "enum": ["ok"], "example": "ok" },
              "service": { "type": "string", "example": "productquant.dev" },
              "time": { "type": "string", "format": "date-time" }
            },
            "required": ["status", "service", "time"]
          }
        },
        "required": ["success", "data"]
      },
      "EndpointInfo": {
        "type": "object",
        "properties": {
          "method": { "type": "string", "enum": ["GET"], "example": "GET" },
          "path": { "type": "string", "example": "/api/health" },
          "description": { "type": "string" }
        },
        "required": ["method", "path", "description"]
      },
      "StatusData": {
        "type": "object",
        "properties": {
          "service": { "type": "string", "example": "ProductQuant" },
          "website": { "type": "string", "format": "uri" },
          "description": { "type": "string" },
          "docs": { "type": "string", "format": "uri" },
          "openapi": { "type": "string", "format": "uri" },
          "llms": { "type": "string", "format": "uri" },
          "contact": { "type": "string", "format": "email" },
          "apiVersion": { "type": "string", "example": "v1" },
          "versioningPolicy": { "type": "string" },
          "deprecationPolicy": { "type": "string", "format": "uri" },
          "endpoints": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/EndpointInfo" }
          },
          "time": { "type": "string", "format": "date-time" }
        },
        "required": ["service", "website", "description", "docs", "openapi", "llms", "contact", "apiVersion", "endpoints", "time"]
      },
      "StatusResponse": {
        "type": "object",
        "properties": {
          "success": { "type": "boolean", "example": true },
          "data": { "$ref": "#/components/schemas/StatusData" }
        },
        "required": ["success", "data"]
      }
    },
    "responses": {
      "NotFound": {
        "description": "Unknown path - RFC 9457 problem document with recovery hint",
        "headers": {
          "X-API-Version": { "$ref": "#/components/headers/XApiVersion" }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Method not supported - only GET, HEAD, OPTIONS are served",
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded - includes Retry-After",
        "headers": {
          "Retry-After": { "$ref": "#/components/headers/RetryAfter" }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" }
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Status",
      "description": "Service health and discovery endpoints"
    }
  ]
}
