{"openapi":"3.1.0","info":{"title":"Ingot API","version":"1.0.0","description":"Ingot (ingot.tools) is a forensic scanner for open-weight AI models. The API serves published scan analyses, verdict badges, patch manifests, runtime guard configs, scan queueing, and deployment release gates. Reads of the public database need no auth; scan queueing and durable deployment records take an API key (`Authorization: Bearer ingot_…`, created in the dashboard). Every error is JSON: `{\"error\": \"<message>\", …}`.","contact":{"url":"https://ingot.tools/contact"}},"servers":[{"url":"https://ingot.tools"}],"security":[],"tags":[{"name":"models","description":"Public scan database — no auth"},{"name":"scans","description":"Queue and poll scans — API key"},{"name":"checks","description":"Stateless deployment release gates — no auth"},{"name":"deployments","description":"Durable deployment records, runs, waivers — API key"}],"paths":{"/api/v1/models/{owner}/{name}":{"get":{"tags":["models"],"operationId":"getModelAnalysis","summary":"Published scan analysis for a model","description":"Verdict, summary, findings with per-finding remediation, battery coverage, and pointers to patch/guard artifacts. 404 means no published analysis yet — queue one via POST /api/v1/scans.","parameters":[{"name":"owner","in":"path","required":true,"description":"Hugging Face repo owner, e.g. `Qwen`.","schema":{"type":"string"}},{"name":"name","in":"path","required":true,"description":"Hugging Face repo name, e.g. `Qwen3.8-27B`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Published analysis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelAnalysis"}}}},"404":{"description":"No published analysis for this model yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/models/{owner}/{name}/badge.svg":{"get":{"tags":["models"],"operationId":"getModelBadge","summary":"Verdict badge (SVG) for READMEs","parameters":[{"name":"owner","in":"path","required":true,"description":"Hugging Face repo owner, e.g. `Qwen`.","schema":{"type":"string"}},{"name":"name","in":"path","required":true,"description":"Hugging Face repo name, e.g. `Qwen3.8-27B`.","schema":{"type":"string"}}],"responses":{"200":{"description":"SVG badge reflecting the latest published verdict ('not scanned' when none)","content":{"image/svg+xml":{"schema":{"type":"string"}}}}}}},"/api/v1/patch/{owner}/{name}":{"get":{"tags":["models"],"operationId":"getPatchManifest","summary":"Patch manifest for a model's metadata-level findings","description":"File operations addressing the model's patchable findings, pinned to the exact upstream revision and content-hashed, plus the honest `unaddressed` list. Applied locally by `npx @ingotai/scan patch` — weights never move.","parameters":[{"name":"owner","in":"path","required":true,"description":"Hugging Face repo owner, e.g. `Qwen`.","schema":{"type":"string"}},{"name":"name","in":"path","required":true,"description":"Hugging Face repo name, e.g. `Qwen3.8-27B`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Patch manifest","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Model not readable via the Hugging Face API","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/guard/{owner}/{name}":{"get":{"tags":["models"],"operationId":"getGuardConfig","summary":"Scan-derived runtime guard config","description":"Confirmed corrupting tokens plus low-norm candidates from the published behavioral battery, content-hashed (`guard_sha256`). Consume directly or via the `@ingotai/guard` npm package. 404 means no behavioral-battery data yet — never 'clean'.","parameters":[{"name":"owner","in":"path","required":true,"description":"Hugging Face repo owner, e.g. `Qwen`.","schema":{"type":"string"}},{"name":"name","in":"path","required":true,"description":"Hugging Face repo name, e.g. `Qwen3.8-27B`.","schema":{"type":"string"}}],"responses":{"200":{"description":"Guard config","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No guard artifact for this model yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/scans":{"post":{"tags":["scans"],"operationId":"createScan","summary":"Queue a scan","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["model"],"properties":{"model":{"type":"string","pattern":"^[\\w.-]+/[\\w.-]+$","description":"Hugging Face repo id, `owner/name`"}}}}}},"responses":{"201":{"description":"Scan queued; poll GET /api/v1/scans/{id}","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"400":{"description":"Malformed body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Daily scan quota reached for your plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/scans/{id}":{"get":{"tags":["scans"],"operationId":"getScan","summary":"Poll a scan","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Scan record (status: queued → running → complete)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"400":{"description":"Invalid scan id","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found (or not your scan)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/check/deployment":{"get":{"tags":["checks"],"operationId":"getDeploymentCheckDocs","summary":"Usage documentation for the deployment check","responses":{"200":{"description":"Usage docs and the published schema location","content":{"application/json":{"schema":{"type":"object"}}}}}},"post":{"tags":["checks"],"operationId":"checkDeployment","summary":"Run the deployment release gates from one manifest","description":"Runs every applicable release gate (stream-conservation, api-integrity, tool-schema-compat) against a canonical deployment-manifest-v1. Static, declared-config evidence: the checks never call your endpoint. Stateless — nothing is persisted. No auth; rate-limited per IP. Filter gates with `?gates=…`. Manifest JSON Schema: /schemas/deployment-manifest-v1.json.","parameters":[{"name":"gates","in":"query","required":false,"description":"Comma-separated subset: stream-conservation,api-integrity,tool-schema-compat","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"A deployment-manifest-v1 document (see /schemas/deployment-manifest-v1.json)"}}}},"responses":{"200":{"description":"Aggregate verdict plus per-gate verdicts and coverage","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid JSON or manifest failed deployment-manifest-v1 validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-IP daily limit for anonymous checks reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/deployments":{"get":{"tags":["deployments"],"operationId":"listDeployments","summary":"List your deployments with their latest verdict","security":[{"apiKey":[]}],"responses":{"200":{"description":"Deployments","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["deployments"],"operationId":"upsertDeployment","summary":"Create or update a deployment from a manifest","description":"Keyed by manifest name + environment. With `check: true` the release gates run immediately and the durable run is returned alongside the deployment.","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["manifest"],"properties":{"manifest":{"type":"object","description":"deployment-manifest-v1"},"check":{"type":"boolean"},"runner":{"type":"string"}}}}}},"responses":{"200":{"description":"Deployment (and run, when check: true)","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Manifest failed validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/deployments/{id}":{"get":{"tags":["deployments"],"operationId":"getDeployment","summary":"Deployment detail","description":"Manifest revision, waivers, run history, and the diff since the previous run.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deployment detail","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/deployments/{id}/checks":{"get":{"tags":["deployments"],"operationId":"listDeploymentChecks","summary":"Run history for a deployment","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Check runs","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["deployments"],"operationId":"runDeploymentCheck","summary":"Re-run the release gates against the stored manifest","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Durable check run","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/deployments/{id}/waivers":{"get":{"tags":["deployments"],"operationId":"listWaivers","summary":"Audit list of waivers on a deployment","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Waivers","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["deployments"],"operationId":"createWaiver","summary":"Accept a risk on a deployment (audited)","description":"Explicit, audited risk acceptance: gate, finding kind, reason, actor, manifest revision. A waived finding keeps its gate at warn, never pass; changing the manifest orphans the waiver unless carried forward.","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Waiver","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Malformed body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/deployments/{id}/waivers/{waiverId}":{"delete":{"tags":["deployments"],"operationId":"revokeWaiver","summary":"Revoke a waiver","security":[{"apiKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"waiverId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Revoked","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"ingot_…","description":"API key from the dashboard: `Authorization: Bearer ingot_…`"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"},"code":{"type":"string","description":"Stable machine-readable code, when applicable"},"hint":{"type":"string","description":"How to resolve the error"}},"additionalProperties":true},"Verdict":{"type":"string","enum":["pass","warn","fail"],"description":"fail = measured, load-bearing damage; warn = measured risk indicator; pass = the measured failure modes came back clean (not a safety certification)."},"Finding":{"type":"object","properties":{"severity":{"type":"string","enum":["high","medium","low","info"]},"kind":{"type":"string"},"title":{"type":"string"},"detail":{"type":"string"},"remediation":{"type":["object","null"]}}},"ModelAnalysis":{"type":"object","properties":{"model":{"type":"string","description":"owner/name"},"verdict":{"$ref":"#/components/schemas/Verdict"},"summary":{"type":"string"},"scanned":{"type":"string"},"source":{"type":"string"},"batteries":{"type":"object","description":"Per-battery scan coverage"},"findings":{"type":"array","items":{"$ref":"#/components/schemas/Finding"}},"remediation_disclaimer":{"type":"string"},"patch":{"type":["string","null"],"description":"Path to the patch manifest, when patchable"},"guard":{"type":["string","null"],"description":"Path to the guard config, when available"},"model_page":{"type":"string"},"fingerprint":{"type":["string","null"]},"report":{"type":["string","null"]}}},"Scan":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"model":{"type":"string"},"status":{"type":"string","enum":["queued","running","complete","error"]},"verdict":{"anyOf":[{"$ref":"#/components/schemas/Verdict"},{"type":"null"}]}},"additionalProperties":true}}}}