{"openapi":"3.1.0","info":{"title":"Sichta Web Scan API","version":"1.0.0","summary":"Trigger and read agent-readiness checks for a verified site.","description":"Every endpoint needs a key: `Authorization: Bearer sichta_...`. Keys are issued in the dashboard under API keys, belong to one account, and may only address sites that account owns.\n\nThe free scan is also available with no key at all over MCP — see /.well-known/mcp.json.","contact":{"name":"Gigliotti Software","email":"hello@gigliotti.software","url":"https://web.sichta.gigliotti.software/docs"},"license":{"name":"Proprietary","url":"https://web.sichta.gigliotti.software/terms"}},"servers":[{"url":"https://web.sichta.gigliotti.software"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Runs","description":"Agent-readiness checks against a verified site."}],"paths":{"/api/v1/sites/{siteId}/runs":{"post":{"tags":["Runs"],"operationId":"createRun","summary":"Run the checks now","description":"Asks us to go and look at the site. This is the only non-GET in the API and it writes nothing to your data. Budgeted at 5 runs per site per day on top of the key's monthly quota, because most of the cost of a run lands on your own server rather than ours.","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string"},"description":"The site id, as shown in its dashboard URL."}],"responses":{"201":{"description":"The completed run.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"The key's monthly request quota."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left this month."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"401":{"description":"Key missing, unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key's account does not own this site, or its plan does not include the API.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such site.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Domain ownership is not verified yet.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Monthly quota spent, or this site's daily run budget is used up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sites/{siteId}/runs/latest":{"get":{"tags":["Runs"],"operationId":"getLatestRun","summary":"The most recent completed run","description":"404 rather than an empty run when nothing has been checked yet: \"no run\" and \"a run that found nothing\" are different states, and conflating them would let a caller believe a site had been checked.","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string"},"description":"The site id, as shown in its dashboard URL."}],"responses":{"200":{"description":"The run and every finding in it.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"The key's monthly request quota."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left this month."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"401":{"description":"Key missing, unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not your site, or the plan does not include the API.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such site, or it has no completed runs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Monthly quota spent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/sites/{siteId}/runs/{number}":{"get":{"tags":["Runs"],"operationId":"getRun","summary":"One run by number","description":"Runs are immutable once finished: this returns what the engine said that day.","parameters":[{"name":"siteId","in":"path","required":true,"schema":{"type":"string"},"description":"The site id, as shown in its dashboard URL."},{"name":"number","in":"path","required":true,"schema":{"type":"integer","minimum":1},"description":"The per-site run number."}],"responses":{"200":{"description":"The run and every finding in it.","headers":{"X-RateLimit-Limit":{"schema":{"type":"integer"},"description":"The key's monthly request quota."},"X-RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left this month."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"400":{"description":"The run number is not a positive integer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Key missing, unknown or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not your site, or the plan does not include the API.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such site or run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Monthly quota spent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"sichta_...","description":"An API key from the dashboard."}},"schemas":{"Finding":{"type":"object","required":["checkId","pillar","scored","result","errorType","detail","title","explanation","fix"],"properties":{"checkId":{"type":"string","enum":["C-LLMS-01","C-LLMS-02","C-LLMS-03","C-LLMS-04","C-SITE-01","C-SITE-02","C-BOT-01","C-BOT-02","C-BOT-03","C-SD-01","C-SD-02","C-SD-03","C-SD-04","C-WK-01","C-WK-02","C-WK-03","C-MD-01","C-FWD-01"]},"pillar":{"type":["string","null"],"enum":["A","B","C","D",null],"description":"A discovery surface, B access policy, C structured data, D machine endpoints."},"scored":{"type":"boolean","description":"Whether this finding counted towards the run's score. Stored per finding, not looked up: a check that moves between scored and forward must not rewrite past runs."},"result":{"type":"string","enum":["PASS","FAIL","UNDETERMINED","NOT_APPLICABLE"]},"errorType":{"type":["string","null"],"enum":["BLOCKED","BROKEN_SAMEAS","DEAD_LINK","ENTITY_INCOMPLETE","FORMAT","INVALID_MANIFEST","MISSING","NO_JSONLD","NO_NEGOTIATION","OVERSIZE","POLICY_INCONSISTENT","SCHEMA_MISMATCH","STRUCTURE","TIMEOUT","UA_REJECTED","UNREACHABLE","WK_UNREACHABLE","WRONG_MIME",null],"description":"Set on FAIL, null otherwise."},"detail":{"type":["string","null"],"description":"What was observed. Never fetched page content."},"title":{"type":["string","null"]},"explanation":{"type":["string","null"]},"fix":{"type":["string","null"]}}},"RunResponse":{"type":"object","required":["site","run","findings"],"properties":{"site":{"type":"object","required":["id","hostname"],"properties":{"id":{"type":"string"},"hostname":{"type":"string"}}},"run":{"type":"object","required":["number","reference","score","trigger","startedAt","finishedAt"],"properties":{"number":{"type":"integer","description":"Gapless, per site, starting at 1."},"reference":{"type":"string","example":"CR-000042"},"score":{"type":["integer","null"],"description":"0-100 over scored, applicable checks. Null means nothing scorable could be determined — it is not a zero."},"trigger":{"type":"string","enum":["MANUAL","SCHEDULED","POST_DEPLOY","API"]},"startedAt":{"type":"string","format":"date-time"},"finishedAt":{"type":["string","null"],"format":"date-time"}}},"findings":{"type":"array","items":{"type":"object","required":["checkId","pillar","scored","result","errorType","detail","title","explanation","fix"],"properties":{"checkId":{"type":"string","enum":["C-LLMS-01","C-LLMS-02","C-LLMS-03","C-LLMS-04","C-SITE-01","C-SITE-02","C-BOT-01","C-BOT-02","C-BOT-03","C-SD-01","C-SD-02","C-SD-03","C-SD-04","C-WK-01","C-WK-02","C-WK-03","C-MD-01","C-FWD-01"]},"pillar":{"type":["string","null"],"enum":["A","B","C","D",null],"description":"A discovery surface, B access policy, C structured data, D machine endpoints."},"scored":{"type":"boolean","description":"Whether this finding counted towards the run's score. Stored per finding, not looked up: a check that moves between scored and forward must not rewrite past runs."},"result":{"type":"string","enum":["PASS","FAIL","UNDETERMINED","NOT_APPLICABLE"]},"errorType":{"type":["string","null"],"enum":["BLOCKED","BROKEN_SAMEAS","DEAD_LINK","ENTITY_INCOMPLETE","FORMAT","INVALID_MANIFEST","MISSING","NO_JSONLD","NO_NEGOTIATION","OVERSIZE","POLICY_INCONSISTENT","SCHEMA_MISMATCH","STRUCTURE","TIMEOUT","UA_REJECTED","UNREACHABLE","WK_UNREACHABLE","WRONG_MIME",null],"description":"Set on FAIL, null otherwise."},"detail":{"type":["string","null"],"description":"What was observed. Never fetched page content."},"title":{"type":["string","null"]},"explanation":{"type":["string","null"]},"fix":{"type":["string","null"]}}}}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}