{"openapi":"3.1.0","info":{"title":"is-aesthetic report API","version":"1.0.0","summary":"Design reports for public web pages: a score, six domains, findings with element evidence and fixes.","description":"Read the latest report for a host, or start a scan. Scans run in isolated browsers, read only, and honour robots.txt. No key is needed. Methodology: https://is-aesthetic.com/methodology","contact":{"url":"https://is-aesthetic.com/docs"}},"servers":[{"url":"https://is-aesthetic.com"}],"paths":{"/api/v1/report":{"get":{"operationId":"getReport","summary":"Latest report for a URL's host","description":"Returns the latest completed report, or the active job. Never starts a scan.","parameters":[{"name":"url","in":"query","required":true,"description":"Absolute http(s) URL, percent-encoded.","schema":{"type":"string","format":"uri"}}],"responses":{"200":{"description":"The report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Report"}},"text/markdown":{"schema":{"type":"string"}}}},"202":{"description":"A scan is queued or running.","headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling again.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Not an absolute, credential-free http(s) URL on a default port.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"unsafe_url: the address is not public.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"not_found: no report for this host yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"The last scan failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FailedJob"}}}},"429":{"description":"Rate limited.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling again.","schema":{"type":"integer"}}}},"503":{"description":"Temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling again.","schema":{"type":"integer"}}}}}},"post":{"operationId":"startScan","summary":"Start a scan","description":"Starts a scan of the URL's host. Repeating the request while that host is queued or running returns the same job.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["url"],"properties":{"url":{"type":"string","format":"uri","maxLength":2048}}}}}},"responses":{"202":{"description":"The scan's job.","headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling again.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Job"}}}},"400":{"description":"Invalid URL or body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"unsafe_url or robots_denied.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Body over 4 KB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"rate_limited or capacity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling again.","schema":{"type":"integer"}}}},"503":{"description":"Temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before retrying or polling again.","schema":{"type":"integer"}}}}}}},"/api/v1/evidence":{"get":{"operationId":"getEvidence","summary":"An element crop or thumbnail from a report","parameters":[{"name":"path","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"A WebP image.","content":{"image/webp":{}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/r/{host}/report.md":{"get":{"operationId":"getReportMarkdown","summary":"Latest report for a host, as Markdown","parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Markdown report.","content":{"text/markdown":{"schema":{"type":"string"}}}},"404":{"description":"No report yet."}}}}},"components":{"schemas":{"Report":{"title":"is-aesthetic report v1","type":"object","$defs":{"box":{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4},"paintedElement":{"type":"object","required":["selector","box"],"properties":{"selector":{"type":"string"},"box":{"$ref":"#/$defs/box"},"elementBox":{"$ref":"#/$defs/box"}}}},"required":["schemaVersion","id","status","url","host","scannedAt","durationMs","pages","score","grade","domains","checks","notCovered","coverage","engine"],"properties":{"rescan":{"type":"object","required":["status","started"],"properties":{"status":{"enum":["queued","running","failed"]},"started":{"type":"string","format":"date-time"},"reason":{"type":"string"}},"description":"A newer rescan while this last complete report remains available. Failed includes expired or incompletely captured rescans."},"schemaVersion":{"const":"1.0"},"id":{"type":"string"},"status":{"const":"complete"},"captureStatus":{"enum":["complete","partial","blocked"],"description":"Requested-page completeness; extra pages are best effort. status still indicates job completion."},"captureReason":{"type":"string"},"url":{"type":["string","null"],"format":"uri"},"host":{"type":["string","null"]},"scannedAt":{"type":"string","format":"date-time"},"durationMs":{"type":"integer","minimum":0},"score":{"type":["number","null"]},"grade":{"enum":["A","B","C","D","F",null]},"thumbnailUrl":{"type":["string","null"]},"reportUrl":{"type":["string","null"]},"pages":{"type":"array","maxItems":3,"items":{"type":"object","required":["url","status","viewports"],"properties":{"url":{"type":"string"},"finalUrl":{"type":"string"},"title":{"type":"string"},"status":{"enum":["captured","partial","blocked"]},"viewports":{"type":"array","items":{"type":"integer"}},"error":{"type":"string"},"notScannedReason":{"type":"string","description":"Why a best-effort extra page did not contribute to scoring."},"blockedBySite":{"type":"boolean"},"dims":{"type":"object","additionalProperties":{"type":"array","items":{"type":"number"},"minItems":2,"maxItems":2},"description":"Document dimensions in CSS pixels, keyed by viewport width; older reports may omit this."},"layout":{"type":"object","additionalProperties":{"type":"array","maxItems":5000,"items":{"type":"array","prefixItems":[{"enum":["text","heading","media","control","region"]},{"type":"number"},{"type":"number"},{"type":"number"},{"type":"number"}],"items":false,"minItems":5,"maxItems":5}},"description":"Geometry only, in document CSS pixels; no text, colours or image pixels."}}}},"domains":{"type":"array","minItems":6,"maxItems":6,"items":{"type":"object","required":["id","name","score","evaluated","excluded"],"properties":{"id":{"type":"integer","minimum":1,"maximum":6},"name":{"type":"string"},"score":{"type":["number","null"]},"evaluated":{"type":"integer"},"excluded":{"type":"integer"}}}},"checks":{"type":"array","items":{"type":"object","required":["id","domain","tier","outcome","value","threshold","evidence","fix","pageUrl"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"domain":{"type":"integer","minimum":1,"maximum":6},"tier":{"enum":["essential","recommended","bonus"]},"outcome":{"enum":["pass","warn","fail","excluded"]},"pageUrl":{"type":"string","format":"uri"},"pageIndex":{"type":"integer","minimum":0,"maximum":2},"value":{},"threshold":{"type":"object","required":["pass","warn","fail"],"properties":{"pass":{"type":"string"},"warn":{"type":"string"},"fail":{"type":"string"}}},"evidence":{"type":"array","items":{"type":"object","required":["cropUrl","box","viewport"],"properties":{"cropUrl":{"type":["string","null"]},"box":{"description":"Original element [x, y, width, height] in document CSS pixels at evidence.viewport, not the retained crop footprint. Coordinates increase rightward and downward from the document origin.","oneOf":[{"type":"array","items":{"type":"number"},"minItems":4,"maxItems":4},{"type":"null"}]},"viewport":{"type":["integer","null"],"description":"Capture viewport width in CSS pixels; crop geometry applies only to this viewport."},"selector":{"type":["string","null"]},"note":{"type":"string"},"pair":{"type":"object","required":["covered","covering","intersection","smallerAreaFraction"],"properties":{"covered":{"$ref":"#/$defs/paintedElement"},"covering":{"$ref":"#/$defs/paintedElement"},"intersection":{"$ref":"#/$defs/box"},"smallerAreaFraction":{"type":"number","minimum":0,"maximum":1}}},"cropSize":{"description":"Exported image [width, height] in pixels; version 1 records the encoded WebP dimensions after resizing.","type":"array","items":{"type":"integer","minimum":1,"maximum":600},"minItems":2,"maxItems":2},"cropScale":{"type":"number","exclusiveMinimum":0,"description":"Version 1: cropSize[0] / cropBox[2], equal to cropScaleXY[0]. Positive real output pixels per CSS pixel, not capture device scale. Legacy reports retain the historical value 2 without establishing trustworthy crop geometry."},"cropGeometryVersion":{"const":1,"description":"Optional geometry contract. When present, requires a retained image and complete cropBox, cropSize, cropScale and cropScaleXY metadata. Reports without it retain legacy semantics."},"cropBox":{"type":"array","prefixItems":[{"type":"number"},{"type":"number"},{"type":"number","exclusiveMinimum":0},{"type":"number","exclusiveMinimum":0}],"items":false,"minItems":4,"maxItems":4,"description":"Actual retained [x, y, width, height] in document CSS pixels at evidence.viewport, with x increasing rightward and y downward. Coordinates must be finite and may be signed (for example RTL scrolling); width and height must be positive. May be partial, offset, clipped or rounded independently of the original evidence.box. Fractional CSS coordinates and dimensions are allowed."},"cropScaleXY":{"type":"array","items":{"type":"number","exclusiveMinimum":0},"minItems":2,"maxItems":2,"description":"Output pixels per document CSS pixel on [x, y]: [cropSize[0] / cropBox[2], cropSize[1] / cropBox[3]]. Positive real ratios may differ due to integer output rounding. Cross-field ratio equality requires verification beyond JSON Schema."},"boxesByViewport":{"type":"object","additionalProperties":{"$ref":"#/$defs/box"}}},"dependentRequired":{"cropBox":["cropGeometryVersion"],"cropScaleXY":["cropGeometryVersion"]},"if":{"required":["cropGeometryVersion"]},"then":{"required":["cropBox","cropSize","cropScale","cropScaleXY"],"properties":{"cropUrl":{"type":"string","minLength":1},"box":{"$ref":"#/$defs/box"},"viewport":{"type":"integer","minimum":1}}},"else":{"properties":{"cropScale":{"const":2}}}}},"fix":{"type":["string","null"]},"exclusionReason":{"type":"string"},"variant":{"enum":["as-written","fixed"]},"impl":{"type":"string"},"summary":{"type":"string"},"method":{"enum":["axe","programmatic","scripted"]},"measured":{"type":"string"},"points":{"type":"number","minimum":0},"maxPoints":{"type":"number","minimum":0}}}},"notCovered":{"type":"array","items":{"type":"string"}},"coverage":{"type":"object","required":["evaluated","excluded","rulesRun"],"properties":{"evaluated":{"type":"integer"},"excluded":{"type":"integer"},"rulesRun":{"type":"array","items":{"type":"string"}}}},"engine":{"type":"object","required":["revision","artifactSha256","registrySha256","axeVersion"],"properties":{"revision":{"type":"string"},"artifactSha256":{"type":"string"},"registrySha256":{"type":"string"},"axeVersion":{"type":"string"}}},"tiers":{"type":"array","items":{"type":"object","required":["tier","earned","possible","evaluated","excluded"],"properties":{"tier":{"enum":["essential","recommended","bonus"]},"earned":{"type":"number"},"possible":{"type":"number"},"evaluated":{"type":"integer"},"excluded":{"type":"integer"}}}},"source":{"oneOf":[{"type":"object","required":["type"],"properties":{"type":{"const":"url"}},"additionalProperties":false},{"type":"object","required":["type","title","bytes","sha256"],"properties":{"type":{"const":"html"},"title":{"type":"string","maxLength":200},"bytes":{"type":"integer","minimum":1,"maximum":2097152},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"additionalProperties":false}]},"judging":{"type":"object","required":["status","limitations"],"properties":{"status":{"enum":["disabled","queued","running","complete","partial","failed","budget_exhausted"]},"provider":{"type":"string"},"model":{"type":"string"},"resolvedModels":{"type":"array","items":{"type":"string"}},"startedAt":{"type":"string","format":"date-time"},"completedAt":{"type":"string","format":"date-time"},"limitations":{"type":"array","items":{"type":"string"}},"findings":{"type":"array","items":{"type":"object","required":["pageUrl","checkId","reason","verdict"],"properties":{"pageUrl":{"type":"string"},"checkId":{"type":"string"},"reason":{"type":"string","minLength":1,"maxLength":200},"verdict":{"enum":["confirmed","likely_false","unsure"]},"evidence":{"type":"array","items":{"type":"integer","minimum":0}}}}},"rubric":{"type":"array","items":{"type":"object","required":["pageUrl","checkId","reason","status"],"properties":{"pageUrl":{"type":"string"},"checkId":{"type":"string"},"reason":{"type":"string","minLength":1,"maxLength":200},"status":{"enum":["pass","warn","fail","unsure"]}}}}},"description":"Agent judgments only. Never included in score, grade, domains, tiers or deterministic check outcomes."}},"allOf":[{"if":{"required":["source"],"properties":{"source":{"properties":{"type":{"const":"html"}}}}},"then":{"properties":{"url":{"type":"null"},"host":{"type":"null"},"reportUrl":{"type":"string","pattern":"^/p/[A-Za-z0-9_-]{32}$"}}},"else":{"properties":{"url":{"type":"string","format":"uri"},"host":{"type":"string"}}}}]},"Job":{"type":"object","required":["id","url","host","status","createdAt","updatedAt","pollUrl"],"properties":{"id":{"type":"string"},"url":{"type":"string","format":"uri"},"host":{"type":"string"},"status":{"enum":["queued","running"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"pollUrl":{"type":"string"},"stage":{"enum":["queued","loading","capturing","checking","saving"]}}},"FailedJob":{"type":"object","required":["id","host","status","error"],"properties":{"id":{"type":"string"},"host":{"type":"string"},"status":{"const":"failed"},"error":{"type":"object","required":["code","message","retryable"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"retryable":{"type":"boolean"}}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","retryable"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"retryable":{"type":"boolean"}}}}}}}}