{"openapi":"3.0.3","info":{"title":"ClamGate","version":"0.1.0","description":"Anonymous asynchronous file scanning. Keep the returned per-job access key private. File bytes are retained only for scanning."},"components":{"securitySchemes":{"applicationToken":{"type":"http","scheme":"bearer","description":"Optional application token on submission only. Verifies the caller name; does not bypass scan or capacity limits."},"jobAccess":{"type":"http","scheme":"bearer","description":"Per-job key returned by POST /api/v1/scans. No account needed."}},"schemas":{}},"paths":{"/api/v1/scans":{"post":{"summary":"Submit a file without an account","description":"Send raw bytes, or a multipart file field named file. Maximum 2147483645 bytes for anonymous and authenticated applications. Optional Authorization: Bearer application token identifies a registered application; invalid tokens return 401. X-Scan-Nonce is a client-generated random base64url value of 22–128 characters. No automatic submission retries: a lost acknowledgement may require a fresh upload; orphaned jobs expire.","parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{22,128}$"},"in":"header","name":"x-scan-nonce","required":true},{"schema":{"type":"string","maxLength":80,"pattern":"^[a-zA-Z0-9 ._-]*$"},"in":"header","name":"x-client-name","required":false,"description":"Optional unverified caller label, not authentication"}],"security":[{},{"applicationToken":[]}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["id","accessKey"],"properties":{"id":{"type":"string","format":"uuid"},"accessKey":{"type":"string"}}}}}}},"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}},"multipart/form-data":{"schema":{"type":"object","required":["file"],"properties":{"file":{"type":"string","format":"binary"}}}}}}}},"/api/v1/scans/{id}":{"get":{"summary":"Retrieve scan status and signed result","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"jobAccess":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","required":["id","state","createdAt","size","reason","result"],"properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["uploading","queued","scanning","clean","infected","rejected","failed","cancelled"]},"createdAt":{"type":"number"},"size":{"type":"number"},"reason":{"type":["null","string"]},"result":{"type":["null","string"],"description":"Compact JWS terminal result; verify with a previously trusted public key."}}}}}}}},"delete":{"summary":"Cancel a scan and delete its temporary file","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"jobAccess":[]}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"accepted":{"type":"boolean"}}}}}}}}},"/api/v1/scans/{id}/events":{"get":{"summary":"Receive lifecycle events as SSE","description":"Use an Authorization header with fetch streaming. Connections end at a terminal outcome or after 60 seconds. Reconnect or use polling; events are not a replay log.","parameters":[{"schema":{"type":"string","format":"uuid"},"in":"path","name":"id","required":true}],"security":[{"jobAccess":[]}],"responses":{"200":{"description":"Default Response"}}}}},"servers":[{"url":"/","description":"Current service origin"},{"url":"https://virus.heerlab.com"},{"url":"https://virus.skyway.tools"}]}