{
  "openapi": "3.1.0",
  "info": {
    "title": "WorldClass Estimates API",
    "version": "1.0.0",
    "summary": "Public REST API for WorldClass Estimates (worldclassestimates.com).",
    "description": "Machine-readable contract for the WorldClass Estimates API.\n\n## Overview\nThe `/v1` API is public and read-only (plus a lead-submission endpoint). It exposes the firm's business information — company profile, services, certifications, coverage, and blog content — as JSON, so agents can integrate without scraping HTML. No authentication or API key is required.\n\n## Versioning & deprecation\nThe API is versioned in the URL path (`/v1/...`). Breaking changes ship under a new path prefix (`/v2/...`). When an endpoint or version is deprecated it returns a `Deprecation: true` header and a `Sunset: <http-date>` header (RFC 8594), and the timeline is published at https://www.worldclassestimates.com/developers#versioning . Additive, backward-compatible changes are made in place within a version.\n\n## Errors\nAll `/v1` errors use RFC 9457 `application/problem+json` with a stable machine-readable `code`, a human-readable `title`/`detail`, and an optional `hint`. The legacy `/api/*` form endpoints return a JSON error object with `ok:false`, `error`, and `code`.\n\n## Rate limits\nEvery `/v1` response carries standard rate-limit headers (`RateLimit-Limit`, `RateLimit-Remaining`, `RateLimit-Reset`, plus the `RateLimit`/`RateLimit-Policy` structured fields). On `429` a `Retry-After` header is returned. See https://www.worldclassestimates.com/developers#rate-limits .\n\n## Content negotiation\nPage URLs also return Markdown when requested with `Accept: text/markdown` (acceptmarkdown.com).\n\nDeveloper portal: https://www.worldclassestimates.com/developers",
    "contact": {
      "name": "WorldClass Estimates",
      "email": "estimator@worldclassestimates.com",
      "url": "https://www.worldclassestimates.com/developers"
    },
    "license": { "name": "Proprietary" }
  },
  "servers": [
    { "url": "https://www.worldclassestimates.com", "description": "Production" }
  ],
  "externalDocs": {
    "description": "Developer portal",
    "url": "https://www.worldclassestimates.com/developers"
  },
  "tags": [
    { "name": "Meta", "description": "API discovery and health" },
    { "name": "Business", "description": "Company, services, certifications, coverage" },
    { "name": "Content", "description": "Blog content" },
    { "name": "Leads", "description": "Lead / contact submission" }
  ],
  "paths": {
    "/v1": {
      "get": {
        "tags": ["Meta"],
        "operationId": "getApiIndex",
        "summary": "API index / discovery document",
        "responses": {
          "200": {
            "description": "List of available endpoints.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/health": {
      "get": {
        "tags": ["Meta"],
        "operationId": "getHealth",
        "summary": "Health check",
        "responses": {
          "200": {
            "description": "Service is healthy.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Health" },
                "example": { "status": "ok", "version": "v1", "time": "2026-08-27T00:00:00.000Z" }
              }
            }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/company": {
      "get": {
        "tags": ["Business"],
        "operationId": "getCompany",
        "summary": "Company profile, contact, and address",
        "responses": {
          "200": {
            "description": "Company profile.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Company" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/services": {
      "get": {
        "tags": ["Business"],
        "operationId": "getServices",
        "summary": "Services offered and audiences served",
        "responses": {
          "200": {
            "description": "Services and audiences.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/certifications": {
      "get": {
        "tags": ["Business"],
        "operationId": "getCertifications",
        "summary": "Team certifications",
        "responses": {
          "200": {
            "description": "Certifications.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/coverage": {
      "get": {
        "tags": ["Business"],
        "operationId": "getCoverage",
        "summary": "Geographic coverage (on-site vs remote)",
        "responses": {
          "200": {
            "description": "Coverage.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/blog": {
      "get": {
        "tags": ["Content"],
        "operationId": "listBlogPosts",
        "summary": "List blog posts",
        "parameters": [
          {
            "name": "locale",
            "in": "query",
            "schema": { "type": "string", "enum": ["en", "es"], "default": "en" }
          },
          {
            "name": "category",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["for-public-adjusters", "for-attorneys", "for-restoration", "for-funding", "hurricane-prep", "florida-law-codes", "xactimate-knowledge"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of posts.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "400": { "$ref": "#/components/responses/ProblemBadRequest" },
          "404": { "$ref": "#/components/responses/ProblemNotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/blog/{slug}": {
      "get": {
        "tags": ["Content"],
        "operationId": "getBlogPost",
        "summary": "Get a single blog post",
        "parameters": [
          { "name": "slug", "in": "path", "required": true, "schema": { "type": "string" } },
          { "name": "locale", "in": "query", "schema": { "type": "string", "enum": ["en", "es"], "default": "en" } }
        ],
        "responses": {
          "200": {
            "description": "Blog post with Markdown body.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BlogPost" } } }
          },
          "400": { "$ref": "#/components/responses/ProblemBadRequest" },
          "404": { "$ref": "#/components/responses/ProblemNotFound" },
          "429": { "$ref": "#/components/responses/RateLimited" }
        }
      }
    },
    "/v1/leads": {
      "post": {
        "tags": ["Leads"],
        "operationId": "submitLead",
        "summary": "Submit a lead / contact request",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/LeadRequest" },
              "example": { "name": "Jane Doe", "email": "jane@example.com", "firm": "Doe PA", "role": "Public Adjuster", "message": "Need a supplement estimate on a FL water loss." }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Lead received.",
            "headers": { "$ref": "#/components/headers/RateLimitSet" },
            "content": { "application/json": { "schema": { "type": "object" }, "example": { "ok": true, "received": "2026-08-27T00:00:00.000Z", "message": "Lead received. The team responds within 24 business hours." } } }
          },
          "400": { "$ref": "#/components/responses/ProblemBadRequest" },
          "405": { "$ref": "#/components/responses/ProblemMethodNotAllowed" },
          "429": { "$ref": "#/components/responses/RateLimited" },
          "502": { "$ref": "#/components/responses/ProblemError" },
          "503": { "$ref": "#/components/responses/ProblemError" }
        }
      }
    },
    "/api/contact": {
      "post": {
        "tags": ["Leads"],
        "operationId": "submitContact",
        "summary": "Submit the website contact form (legacy)",
        "description": "Backs the site's contact form. Returns the legacy JSON error envelope. Prefer POST /v1/leads for programmatic use.",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ContactRequest" } } }
        },
        "responses": {
          "200": { "description": "Accepted.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/OkResponse" } } } },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/lead-magnet": {
      "post": {
        "tags": ["Leads"],
        "operationId": "requestLeadMagnet",
        "summary": "Request a lead-magnet guide (legacy)",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeadMagnetRequest" } } }
        },
        "responses": {
          "200": { "description": "Guide sent.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/lead-magnet-step2": {
      "post": {
        "tags": ["Leads"],
        "operationId": "submitLeadMagnetStep2",
        "summary": "Submit optional lead-magnet follow-up (legacy)",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LeadMagnetStep2Request" } } }
        },
        "responses": {
          "200": { "description": "Saved.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } } },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    },
    "/api/storm-maps-signup": {
      "post": {
        "tags": ["Leads"],
        "operationId": "submitStormMapsSignup",
        "summary": "Sign up for storm-maps access (legacy)",
        "requestBody": {
          "required": true,
          "content": { "application/json": { "schema": { "$ref": "#/components/schemas/StormMapsSignupRequest" } } }
        },
        "responses": {
          "200": {
            "description": "Access granted. Sets the wce_maps_access cookie.",
            "headers": { "Set-Cookie": { "description": "wce_maps_access=true (90-day cookie).", "schema": { "type": "string" } } },
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessResponse" } } }
          },
          "400": { "$ref": "#/components/responses/ValidationError" },
          "405": { "$ref": "#/components/responses/MethodNotAllowed" },
          "500": { "$ref": "#/components/responses/InternalError" }
        }
      }
    }
  },
  "components": {
    "headers": {
      "RateLimitSet": {
        "description": "Standard rate-limit headers are present on every /v1 response.",
        "schema": { "type": "string" }
      }
    },
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details.",
        "required": ["type", "title", "status", "code"],
        "properties": {
          "type": { "type": "string", "format": "uri", "description": "URI reference identifying the problem type." },
          "title": { "type": "string", "description": "Short, human-readable summary." },
          "status": { "type": "integer", "description": "HTTP status code." },
          "code": { "type": "string", "description": "Stable machine-readable error code.", "examples": ["invalid_locale", "unknown_category", "post_not_found", "not_found", "rate_limited", "method_not_allowed", "missing_fields", "invalid_email", "field_too_long", "invalid_json"] },
          "detail": { "type": "string", "description": "Human-readable explanation." },
          "hint": { "type": "string", "description": "Optional guidance on how to resolve the error." },
          "instance": { "type": "string", "description": "URI reference for the specific occurrence." }
        }
      },
      "Health": {
        "type": "object",
        "required": ["status", "version", "time"],
        "properties": {
          "status": { "type": "string", "const": "ok" },
          "version": { "type": "string" },
          "time": { "type": "string", "format": "date-time" }
        }
      },
      "Company": {
        "type": "object",
        "properties": {
          "name": { "type": "string" },
          "description": { "type": "string" },
          "url": { "type": "string", "format": "uri" },
          "email": { "type": "string", "format": "email" },
          "phones": { "type": "array", "items": { "type": "string" } },
          "languages": { "type": "array", "items": { "type": "string" } },
          "address": { "$ref": "#/components/schemas/PostalAddress" },
          "socialProfiles": { "type": "array", "items": { "type": "string", "format": "uri" } }
        }
      },
      "PostalAddress": {
        "type": "object",
        "properties": {
          "streetAddress": { "type": "string" },
          "addressLocality": { "type": "string" },
          "addressRegion": { "type": "string" },
          "postalCode": { "type": "string" },
          "addressCountry": { "type": "string" }
        }
      },
      "BlogPost": {
        "type": "object",
        "properties": {
          "slug": { "type": "string" },
          "title": { "type": "string" },
          "locale": { "type": "string" },
          "category": { "type": "string" },
          "publishDate": { "type": "string" },
          "author": { "type": "string" },
          "description": { "type": "string" },
          "readingTime": { "type": "number" },
          "url": { "type": "string", "format": "uri" },
          "contentFormat": { "type": "string", "const": "markdown" },
          "content": { "type": "string" }
        }
      },
      "LeadRequest": {
        "type": "object",
        "required": ["name", "email", "message"],
        "properties": {
          "name": { "type": "string", "maxLength": 100 },
          "email": { "type": "string", "format": "email", "maxLength": 254 },
          "message": { "type": "string", "maxLength": 5000 },
          "firm": { "type": "string", "maxLength": 100 },
          "role": { "type": "string", "maxLength": 50 },
          "phone": { "type": "string", "maxLength": 30 }
        }
      },
      "OkResponse": {
        "type": "object",
        "required": ["ok"],
        "properties": { "ok": { "type": "boolean", "const": true } }
      },
      "SuccessResponse": {
        "type": "object",
        "required": ["success"],
        "properties": { "success": { "type": "boolean", "const": true } }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Legacy JSON error envelope used by /api/* form endpoints.",
        "required": ["ok", "error", "code"],
        "properties": {
          "ok": { "type": "boolean", "const": false },
          "success": { "type": "boolean" },
          "error": { "type": "string" },
          "code": { "type": "string", "examples": ["missing_fields", "invalid_email", "field_too_long", "unknown_magnet", "method_not_allowed", "internal_error", "not_found"] },
          "hint": { "type": "string" }
        }
      },
      "ContactRequest": {
        "type": "object",
        "required": ["name", "email", "firm", "role", "message"],
        "properties": {
          "name": { "type": "string", "minLength": 2, "maxLength": 100 },
          "email": { "type": "string", "format": "email", "maxLength": 254 },
          "firm": { "type": "string", "maxLength": 100 },
          "role": { "type": "string", "maxLength": 50 },
          "message": { "type": "string", "minLength": 10, "maxLength": 5000 }
        }
      },
      "LeadMagnetRequest": {
        "type": "object",
        "required": ["firstName", "email", "audience", "magnetSlug"],
        "properties": {
          "firstName": { "type": "string" },
          "email": { "type": "string", "format": "email" },
          "audience": { "type": "string" },
          "magnetSlug": { "type": "string", "examples": ["pa-checklist", "attorneys-audit", "restoration-guide"] },
          "leadSource": { "type": "string" },
          "landingUrl": { "type": "string", "format": "uri" }
        }
      },
      "LeadMagnetStep2Request": {
        "type": "object",
        "required": ["email"],
        "properties": {
          "email": { "type": "string", "format": "email" },
          "phone": { "type": "string" },
          "state": { "type": "string" }
        }
      },
      "StormMapsSignupRequest": {
        "type": "object",
        "required": ["fullName", "email", "company", "role"],
        "properties": {
          "fullName": { "type": "string", "maxLength": 100 },
          "email": { "type": "string", "format": "email", "maxLength": 254 },
          "company": { "type": "string", "maxLength": 100 },
          "role": { "type": "string", "maxLength": 60 },
          "phone": { "type": "string", "maxLength": 30 }
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "Rate limit exceeded (RFC 9457).",
        "headers": {
          "Retry-After": { "description": "Seconds until the limit resets.", "schema": { "type": "integer" } },
          "RateLimit-Limit": { "schema": { "type": "integer" } },
          "RateLimit-Remaining": { "schema": { "type": "integer" } },
          "RateLimit-Reset": { "schema": { "type": "integer" } }
        },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" },
            "example": { "type": "https://www.worldclassestimates.com/developers#error-rate_limited", "title": "Too Many Requests", "status": 429, "code": "rate_limited", "detail": "You have exceeded the request rate limit.", "hint": "Retry after 60 seconds." }
          }
        }
      },
      "ProblemBadRequest": {
        "description": "Invalid request (RFC 9457).",
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" },
            "example": { "type": "https://www.worldclassestimates.com/developers#error-invalid_locale", "title": "Invalid locale", "status": 400, "code": "invalid_locale", "detail": "Unsupported locale \"fr\".", "hint": "Supported locales: en, es." }
          }
        }
      },
      "ProblemNotFound": {
        "description": "Resource not found (RFC 9457).",
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" },
            "example": { "type": "https://www.worldclassestimates.com/developers#error-post_not_found", "title": "Post not found", "status": 404, "code": "post_not_found", "detail": "No blog post \"x\" for locale \"en\"." }
          }
        }
      },
      "ProblemMethodNotAllowed": {
        "description": "Method not allowed (RFC 9457).",
        "headers": { "Allow": { "schema": { "type": "string" } } },
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" },
            "example": { "type": "https://www.worldclassestimates.com/developers#error-method_not_allowed", "title": "Method Not Allowed", "status": 405, "code": "method_not_allowed", "detail": "This endpoint only accepts: POST." }
          }
        }
      },
      "ProblemError": {
        "description": "Server-side error (RFC 9457).",
        "content": {
          "application/problem+json": {
            "schema": { "$ref": "#/components/schemas/Problem" },
            "example": { "type": "https://www.worldclassestimates.com/developers#error-delivery_failed", "title": "Lead delivery failed", "status": 502, "code": "delivery_failed", "detail": "The lead could not be delivered." }
          }
        }
      },
      "ValidationError": {
        "description": "The request failed validation (legacy envelope).",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": { "ok": false, "error": "All fields are required.", "code": "missing_fields", "hint": "Provide name, email, firm, role and message." }
          }
        }
      },
      "MethodNotAllowed": {
        "description": "Unsupported HTTP method (legacy envelope).",
        "headers": { "Allow": { "schema": { "type": "string", "example": "POST" } } },
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": { "ok": false, "error": "This endpoint only accepts: POST.", "code": "method_not_allowed", "hint": "See https://www.worldclassestimates.com/openapi.json for the full API contract." }
          }
        }
      },
      "InternalError": {
        "description": "Unexpected server error (legacy envelope).",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/ErrorResponse" },
            "example": { "ok": false, "error": "Internal error", "code": "internal_error", "hint": "Retry, or email estimator@worldclassestimates.com directly." }
          }
        }
      }
    }
  }
}
