{
  "openapi": "3.1.0",
  "info": {
    "title": "Good Value Solutions public API",
    "version": "1.0.0",
    "description": "Public read-only API for Good Value Solutions site data (company status, project portfolio, service catalog). No authentication required. No writes, no webhooks. Versioned in the URL path: breaking changes ship as a new major version (/api/v2) with at least 90 days notice — see https://goodvaluesolutions.com/docs#versioning for the policy.",
    "termsOfService": "https://goodvaluesolutions.com/terms",
    "contact": {
      "name": "Good Value Solutions",
      "url": "https://goodvaluesolutions.com/contact",
      "email": "info@goodvaluesolutions.com"
    }
  },
  "servers": [
    {
      "url": "https://goodvaluesolutions.com",
      "description": "Production"
    }
  ],
  "externalDocs": {
    "description": "Human-readable API and developer documentation",
    "url": "https://goodvaluesolutions.com/docs"
  },
  "tags": [{ "name": "Site data", "description": "Read-only company data." }],
  "paths": {
    "/api/v1/status": {
      "get": {
        "operationId": "getApiStatus",
        "summary": "Get API status and endpoint list",
        "description": "Returns service status, the endpoint catalog, and links to docs and this spec. Use it to verify connectivity before calling data endpoints.",
        "tags": ["Site data"],
        "security": [],
        "responses": {
          "200": {
            "description": "Service is up",
            "headers": {
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/StatusResponse" }
              }
            }
          },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/v1/projects": {
      "get": {
        "operationId": "listProjects",
        "summary": "List showcased construction projects",
        "description": "Returns the showcased project portfolio with id, title, category, location, year, and featured flag.",
        "tags": ["Site data"],
        "security": [],
        "responses": {
          "200": {
            "description": "Project list",
            "headers": {
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ProjectListResponse" }
              }
            }
          },
          "404": { "$ref": "#/components/responses/EndpointNotFound" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    },
    "/api/v1/services": {
      "get": {
        "operationId": "listServices",
        "summary": "List construction services",
        "description": "Returns the service catalog (warehousing, residential, EPC) with id, title, and description.",
        "tags": ["Site data"],
        "security": [],
        "responses": {
          "200": {
            "description": "Service list",
            "headers": {
              "RateLimit-Policy": { "$ref": "#/components/headers/RateLimitPolicy" }
            },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ServiceListResponse" }
              }
            }
          },
          "404": { "$ref": "#/components/responses/EndpointNotFound" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" }
        }
      }
    }
  },
  "components": {
    "headers": {
      "RateLimitPolicy": {
        "description": "Quota policy: 120 requests per 60-second window per client IP, enforced at the edge. Slow down when responses approach the limit.",
        "schema": { "type": "string", "example": "120;w=60" }
      }
    },
    "responses": {
      "EndpointNotFound": {
        "description": "Unknown endpoint under /api/*.",
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/ProblemDetails" }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Non-GET method used on a read-only endpoint.",
        "headers": {
          "Allow": {
            "description": "Supported methods.",
            "schema": { "type": "string", "example": "GET, HEAD" }
          }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/ProblemDetails" }
          }
        }
      }
    },
    "schemas": {
      "StatusResponse": {
        "type": "object",
        "required": ["site", "status", "timestamp", "docs", "openapi", "endpoints"],
        "properties": {
          "site": { "type": "string", "format": "uri" },
          "status": { "type": "string", "enum": ["ok"] },
          "timestamp": { "type": "string", "format": "date-time" },
          "authentication": { "type": "string" },
          "docs": { "type": "string", "format": "uri" },
          "openapi": { "type": "string", "format": "uri" },
          "endpoints": { "type": "array", "items": { "type": "string" } }
        }
      },
      "ProjectSummary": {
        "type": "object",
        "required": ["id", "title", "category", "location"],
        "properties": {
          "id": { "type": "string", "description": "Slug used in /projects/{id} URLs." },
          "title": { "type": "string" },
          "category": { "type": "string", "enum": ["Warehousing", "Residential", "EPC"] },
          "location": { "type": "string" },
          "year": { "type": "integer" },
          "featured": { "type": "boolean" }
        }
      },
      "ProjectListResponse": {
        "type": "object",
        "required": ["count", "projects"],
        "properties": {
          "count": { "type": "integer", "description": "Number of projects returned." },
          "projects": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ProjectSummary" }
          }
        }
      },
      "ServiceSummary": {
        "type": "object",
        "required": ["title", "description"],
        "properties": {
          "id": { "type": "string" },
          "title": { "type": "string" },
          "description": { "type": "string" }
        }
      },
      "ServiceListResponse": {
        "type": "object",
        "required": ["count", "services"],
        "properties": {
          "count": { "type": "integer", "description": "Number of services returned." },
          "services": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ServiceSummary" }
          }
        }
      },
      "ProblemDetails": {
        "description": "RFC 9457 error for unknown endpoints (404) and wrong methods (405).",
        "type": "object",
        "required": ["status", "code", "detail", "resolution"],
        "properties": {
          "status": { "type": "integer" },
          "code": { "type": "string", "description": "Stable machine-readable code, e.g. endpoint_not_found." },
          "detail": { "type": "string" },
          "resolution": { "type": "string", "description": "What to do next." }
        }
      }
    }
  }
}
