{"openapi":"3.1.0","info":{"title":"WhyDoesMySiteSuck API","version":"1.0.0","summary":"Site-quality scores from a 368-point audit.","description":"Read-only access to website audit scores. Get a free key at https://whydoesmysitesuck.com/api — free keys may start 3 new scans and make 60 requests per minute.","contact":{"email":"answer@whydoesmysitesuck.com","url":"https://whydoesmysitesuck.com/api"}},"servers":[{"url":"https://whydoesmysitesuck.com"}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key"}},"schemas":{"Score":{"type":"object","properties":{"domain":{"type":"string","example":"example.com"},"score":{"type":"integer","minimum":0,"maximum":100,"example":72},"grade":{"type":"string","enum":["A","B","C","D","F"]},"scanned_at":{"type":"string","example":"2026-07-28 09:24:11"},"stale":{"type":"boolean","description":"Older than 30 days; a refresh is running."},"categories":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string","example":"Security"},"score":{"type":"integer","example":95}}}},"report_url":{"type":"string","format":"uri"}}},"Scanning":{"type":"object","description":"No scan on record — one was just started.","properties":{"domain":{"type":"string"},"status":{"type":"string","example":"scanning"},"scan_id":{"type":"string"},"retry_after":{"type":"integer","example":30}}},"Error":{"type":"object","properties":{"error":{"type":"string"}}}}},"security":[{"ApiKeyAuth":[]}],"paths":{"/api/public/domain/{domain}":{"get":{"operationId":"getDomainScore","summary":"Score, grade and category breakdown for a domain","description":"Pass a bare domain, not a URL. If the domain has never been scanned, a scan starts in the background and the call returns 202 — poll the same URL again in about 30 seconds.","parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string"},"example":"example.com"}],"responses":{"200":{"description":"Latest completed scan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Score"}}}},"202":{"description":"Scan started; retry in ~30s","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scanning"}}}},"400":{"description":"Invalid domain","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Last scan of this domain failed; in cooldown"},"429":{"description":"Rate limited (free tier)"}}}},"/api/stats":{"get":{"operationId":"getChecklistStats","summary":"Checklist composition (no key required)","security":[],"responses":{"200":{"description":"Counts by severity, tier and detectability"}}}}}}