{"openapi":"3.1.0","info":{"title":"CleanForge Public API","version":"1.0","description":"Machine-readable CleanForge public API for discovery, capabilities, health checks, pricing estimates, and 6-weekly window cleaning quote requests. Public API discovery starts at /api, v1 discovery is available at /api/v1, capabilities are available at /api/v1/capabilities, and a human-readable developer overview is available at /developers. Compatible with AI agents, GPT Actions, MCP clients, mobile applications, future customer applications, and third-party integrations.","x-api-id":"cleanforge-public-api"},"servers":[{"url":"https://www.cleanforge.co.uk/"}],"security":[],"x-authentication":{"type":"none"},"x-rate-limits":{"quote_requests_per_hour":120,"quote_requests_per_window":20,"quote_request_window_seconds":600},"paths":{"/api":{"get":{"operationId":"getPublicApiDiscovery","summary":"Discover CleanForge public API endpoints","responses":{"200":{"description":"Root public API discovery document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootDiscovery"},"examples":{"production":{"value":{"id":"cleanforge-public-api","name":"CleanForge Public API","version":"1.0","build":null,"generated_at":"2026-06-26T17:32:26.978Z","environment":"production","authentication":{"type":"none"},"limits":{"quote_requests_per_hour":120,"quote_requests_per_window":20,"quote_request_window_seconds":600},"terms":null,"current":"/api/v1","versions":{"v1":"/api/v1"},"links":{"v1":"/api/v1","openapi":"/openapi.json","well_known_openapi":"/.well-known/openapi.json","llms":"/llms.txt"}}}}}}}}}},"/api/v1":{"get":{"operationId":"getPublicApiV1Discovery","summary":"Discover CleanForge public API v1 endpoints","responses":{"200":{"description":"CleanForge public API v1 discovery document","content":{"application/json":{"schema":{"$ref":"#/components/schemas/V1Discovery"},"examples":{"production":{"value":{"id":"cleanforge-public-api","name":"CleanForge Public API","version":"1.0","build":null,"generated_at":"2026-06-26T17:32:26.978Z","environment":"production","authentication":{"type":"none"},"limits":{"quote_requests_per_hour":120,"quote_requests_per_window":20,"quote_request_window_seconds":600},"terms":null,"links":{"capabilities":"/api/v1/capabilities","pricing_estimate":"/api/v1/pricing/estimate","quote_requests":"/api/v1/quote-requests","health":"/api/v1/health","openapi":"/openapi.json","well_known_openapi":"/.well-known/openapi.json","llms":"/llms.txt"}}}}}}}}}},"/api/v1/capabilities":{"get":{"operationId":"getPublicApiCapabilities","summary":"Describe CleanForge public API capabilities","responses":{"200":{"description":"Machine-readable CleanForge capabilities","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Capabilities"},"examples":{"production":{"value":{"id":"cleanforge-public-api","name":"CleanForge Public API","version":"1.0","build":null,"generated_at":"2026-06-26T17:32:26.978Z","environment":"production","authentication":{"type":"none"},"limits":{"quote_requests_per_hour":120,"quote_requests_per_window":20,"quote_request_window_seconds":600},"terms":null,"company":{"name":"CleanForge","website":"https://www.cleanforge.co.uk"},"api_version":"1.0","services":[{"id":"window_cleaning","name":"Window Cleaning","enabled":true}],"quote_requests":{"supported":true,"endpoint":"/api/v1/quote-requests","method":"POST"},"pricing_estimates":{"supported":true,"endpoint":"/api/v1/pricing/estimate","method":"POST","mutates":false},"booking":{"supported":false},"payments":{"supported":false},"customer_portal":{"supported":false},"go_cardless":{"supported":false},"quickbooks":{"supported":false},"commercial_window_cleaning":{"supported":false},"gutter_cleaning":{"supported":false},"pressure_washing":{"supported":false},"roof_cleaning":{"supported":false},"fascia_soffit_cleaning":{"supported":false},"business_rules":{"frequency":"six_weekly","minimum_regular_price":20,"first_clean_multiplier":1.5},"property_types":["flat","maisonette","small_terrace","medium_terrace","large_terrace","semi_detached","detached"],"service_areas":["front","back","front_and_back"],"supported_contact_methods":["email","phone","sms","whatsapp"],"documentation":{"openapi":"/openapi.json","well_known_openapi":"/.well-known/openapi.json","llms":"/llms.txt"},"links":{"capabilities":"/api/v1/capabilities","pricing_estimate":"/api/v1/pricing/estimate","quote_requests":"/api/v1/quote-requests","health":"/api/v1/health","openapi":"/openapi.json","well_known_openapi":"/.well-known/openapi.json","llms":"/llms.txt"}}}}}}}}}},"/api/v1/health":{"get":{"operationId":"getPublicApiHealth","summary":"Check CleanForge public API health","responses":{"200":{"description":"Public API is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"},"examples":{"healthy":{"value":{"status":"healthy","api_version":"1.0"}}}}}}}}},"/api/v1/pricing/estimate":{"post":{"operationId":"estimateWindowCleaningPrice","summary":"Estimate a CleanForge window cleaning price without creating records","description":"Returns an estimated regular clean and first clean price. This endpoint is read-only and does not create leads, quotes, customers, jobs, or database writes.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingEstimateInput"},"examples":{"flat":{"value":{"property":{"postcode":"SW19 1AA","type":"flat","service_areas":"front_and_back"},"service":{"service_type":"window_cleaning","frequency":"six_weekly"}}}}}}},"responses":{"200":{"description":"Pricing estimate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PricingEstimateResponse"},"examples":{"flat":{"value":{"regular_price":20,"first_clean_price":30,"currency":"GBP","estimated":true}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}}}}},"/api/v1/quote-requests":{"post":{"operationId":"createQuoteRequest","summary":"Submit a CleanForge window cleaning quote request","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":200},"description":"Use a stable unique key to prevent duplicate leads on retries."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequestInput"},"examples":{"agent":{"value":{"customer":{"name":"Sam Taylor","email":"sam@example.com"},"property":{"address_line_1":"12 Test Street","postcode":"SW19 1AA","type":"flat","service_areas":"front_and_back"},"service":{"service_type":"window_cleaning","frequency":"six_weekly"},"source":"agent","test_mode":true}}}}}},"responses":{"201":{"description":"Quote request accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteRequestResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorResponse"}}}},"429":{"description":"Rate limited"},"502":{"description":"Submission failed"}}}}},"components":{"schemas":{"RootDiscovery":{"type":"object","required":["id","name","version","build","generated_at","environment","authentication","limits","terms","current","versions","links"],"properties":{"id":{"type":"string","const":"cleanforge-public-api"},"name":{"type":"string","const":"CleanForge Public API"},"version":{"type":"string","const":"1.0"},"build":{"type":["string","null"]},"generated_at":{"type":"string","format":"date-time"},"environment":{"type":"string","enum":["production","staging","development"]},"authentication":{"$ref":"#/components/schemas/Authentication"},"limits":{"$ref":"#/components/schemas/ApiLimits"},"terms":{"type":["string","null"]},"current":{"type":"string","const":"/api/v1"},"versions":{"type":"object","required":["v1"],"properties":{"v1":{"type":"string","const":"/api/v1"}}},"links":{"$ref":"#/components/schemas/RootLinks"}}},"V1Discovery":{"type":"object","required":["id","name","version","build","generated_at","environment","authentication","limits","terms","links"],"properties":{"id":{"type":"string","const":"cleanforge-public-api"},"name":{"type":"string","const":"CleanForge Public API"},"version":{"type":"string","const":"1.0"},"build":{"type":["string","null"]},"generated_at":{"type":"string","format":"date-time"},"environment":{"type":"string","enum":["production","staging","development"]},"authentication":{"$ref":"#/components/schemas/Authentication"},"limits":{"$ref":"#/components/schemas/ApiLimits"},"terms":{"type":["string","null"]},"links":{"$ref":"#/components/schemas/V1Links"}}},"Authentication":{"type":"object","required":["type"],"properties":{"type":{"type":"string","const":"none"}}},"ApiLimits":{"type":"object","required":["quote_requests_per_hour","quote_requests_per_window","quote_request_window_seconds"],"properties":{"quote_requests_per_hour":{"type":"integer"},"quote_requests_per_window":{"type":"integer"},"quote_request_window_seconds":{"type":"integer"}}},"RootLinks":{"type":"object","required":["v1","openapi","well_known_openapi","llms"],"properties":{"v1":{"type":"string","const":"/api/v1"},"openapi":{"type":"string","const":"/openapi.json"},"well_known_openapi":{"type":"string","const":"/.well-known/openapi.json"},"llms":{"type":"string","const":"/llms.txt"}}},"V1Links":{"type":"object","required":["capabilities","pricing_estimate","quote_requests","health","openapi","well_known_openapi","llms"],"properties":{"capabilities":{"type":"string","const":"/api/v1/capabilities"},"pricing_estimate":{"type":"string","const":"/api/v1/pricing/estimate"},"quote_requests":{"type":"string","const":"/api/v1/quote-requests"},"health":{"type":"string","const":"/api/v1/health"},"openapi":{"type":"string","const":"/openapi.json"},"well_known_openapi":{"type":"string","const":"/.well-known/openapi.json"},"llms":{"type":"string","const":"/llms.txt"}}},"CapabilityFlag":{"type":"object","required":["supported"],"properties":{"supported":{"type":"boolean"}},"additionalProperties":true},"Capabilities":{"type":"object","required":["id","company","generated_at","api_version","build","environment","authentication","limits","terms","services","quote_requests","pricing_estimates","booking","payments","customer_portal","business_rules","property_types","service_areas","supported_contact_methods","documentation","links"],"properties":{"id":{"type":"string","const":"cleanforge-public-api"},"build":{"type":["string","null"]},"authentication":{"$ref":"#/components/schemas/Authentication"},"limits":{"$ref":"#/components/schemas/ApiLimits"},"terms":{"type":["string","null"]},"company":{"type":"object","required":["name","website"],"properties":{"name":{"type":"string"},"website":{"type":"string","format":"uri"}}},"generated_at":{"type":"string","format":"date-time"},"api_version":{"type":"string","const":"1.0"},"environment":{"type":"string","enum":["production","staging","development"]},"services":{"type":"array","items":{"type":"object","required":["id","name","enabled"],"properties":{"id":{"type":"string","const":"window_cleaning"},"name":{"type":"string"},"enabled":{"type":"boolean"}}}},"quote_requests":{"type":"object","required":["supported","endpoint","method"],"properties":{"supported":{"type":"boolean","const":true},"endpoint":{"type":"string","const":"/api/v1/quote-requests"},"method":{"type":"string","const":"POST"}}},"pricing_estimates":{"type":"object","required":["supported","endpoint","method","mutates"],"properties":{"supported":{"type":"boolean","const":true},"endpoint":{"type":"string","const":"/api/v1/pricing/estimate"},"method":{"type":"string","const":"POST"},"mutates":{"type":"boolean","const":false}}},"booking":{"$ref":"#/components/schemas/CapabilityFlag"},"payments":{"$ref":"#/components/schemas/CapabilityFlag"},"customer_portal":{"$ref":"#/components/schemas/CapabilityFlag"},"go_cardless":{"$ref":"#/components/schemas/CapabilityFlag"},"quickbooks":{"$ref":"#/components/schemas/CapabilityFlag"},"commercial_window_cleaning":{"$ref":"#/components/schemas/CapabilityFlag"},"gutter_cleaning":{"$ref":"#/components/schemas/CapabilityFlag"},"pressure_washing":{"$ref":"#/components/schemas/CapabilityFlag"},"roof_cleaning":{"$ref":"#/components/schemas/CapabilityFlag"},"fascia_soffit_cleaning":{"$ref":"#/components/schemas/CapabilityFlag"},"business_rules":{"type":"object","required":["frequency","minimum_regular_price","first_clean_multiplier"],"properties":{"frequency":{"type":"string","const":"six_weekly"},"minimum_regular_price":{"type":"integer","const":20},"first_clean_multiplier":{"type":"number","const":1.5}}},"property_types":{"type":"array","items":{"type":"string","enum":["flat","maisonette","small_terrace","medium_terrace","large_terrace","semi_detached","detached"]}},"service_areas":{"type":"array","items":{"type":"string","enum":["front","back","front_and_back"]}},"supported_contact_methods":{"type":"array","items":{"type":"string","enum":["email","phone","sms","whatsapp"]}},"documentation":{"type":"object","required":["openapi","well_known_openapi","llms"],"properties":{"openapi":{"type":"string","const":"/openapi.json"},"well_known_openapi":{"type":"string","const":"/.well-known/openapi.json"},"llms":{"type":"string","const":"/llms.txt"}}},"links":{"$ref":"#/components/schemas/V1Links"}},"additionalProperties":true},"Health":{"type":"object","required":["status","api_version"],"properties":{"status":{"type":"string","const":"healthy"},"api_version":{"type":"string","const":"1.0"}}},"PricingEstimateInput":{"type":"object","required":["property","service"],"properties":{"property":{"type":"object","required":["postcode","type","service_areas"],"properties":{"postcode":{"type":"string"},"type":{"type":"string","enum":["flat","maisonette","small_terrace","medium_terrace","large_terrace","semi_detached","detached"]},"service_areas":{"type":"string","enum":["front","back","front_and_back"]}}},"service":{"type":"object","required":["service_type","frequency"],"properties":{"service_type":{"type":"string","const":"window_cleaning"},"frequency":{"type":"string","const":"six_weekly"}}}}},"PricingEstimateResponse":{"type":"object","required":["regular_price","first_clean_price","currency","estimated"],"properties":{"regular_price":{"type":"integer","minimum":20},"first_clean_price":{"type":"integer","minimum":30},"currency":{"type":"string","const":"GBP"},"estimated":{"type":"boolean","const":true}}},"QuoteRequestInput":{"type":"object","required":["customer","property","service"],"properties":{"customer":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"preferred_contact":{"type":"string","enum":["phone","sms","whatsapp","email","no_preference"]}}},"property":{"type":"object","required":["address_line_1","postcode","type","service_areas"],"properties":{"address_line_1":{"type":"string"},"address_line_2":{"type":"string"},"city":{"type":"string"},"postcode":{"type":"string"},"type":{"type":"string","enum":["flat","maisonette","small_terrace","medium_terrace","large_terrace","semi_detached","detached"]},"service_areas":{"type":"string","enum":["front","back","front_and_back"]}}},"service":{"type":"object","required":["service_type","frequency"],"properties":{"service_type":{"type":"string","const":"window_cleaning"},"frequency":{"type":"string","const":"six_weekly"}}},"notes":{"type":"string"},"source":{"type":"string","description":"Use agent for agent-originated submissions.","enum":["agent","website","canvassing","leaflet","referral","phone","email","google_business_profile","facebook_nextdoor","other"]},"test_mode":{"type":"boolean","description":"When true, the request is clearly marked and excluded from normal production reporting."}}},"QuoteRequestResponse":{"type":"object","required":["quote_request_id","status","estimated_regular_price","estimated_first_clean_price","message"],"properties":{"quote_request_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["received","test_received"]},"estimated_regular_price":{"type":"integer","minimum":20},"estimated_first_clean_price":{"type":"integer","minimum":30},"message":{"type":"string"}}},"ValidationErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","const":"validation_failed"},"message":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}}}}}}}