{"openapi":"3.0.0","info":{"title":"AgentPouch API","version":"0.1.0"},"servers":[{"url":"https://api.agentpouch.sh"}],"components":{"schemas":{"Health":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"db":{"type":"boolean"},"storage":{"type":"boolean"},"uptime_seconds":{"type":"number"}},"required":["status","db","storage","uptime_seconds"]},"HealthDegraded":{"type":"object","properties":{"status":{"type":"string","enum":["degraded"]},"error":{"type":"string"}},"required":["status","error"]},"Reference":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"shortid":{"type":"string"},"agent_link":{"type":"string","format":"uri"},"human_link":{"type":"string","format":"uri"},"sha256":{"type":"string","minLength":64,"maxLength":64},"mime":{"type":"string"},"size":{"type":"integer","minimum":0},"filename":{"type":"string"},"direction":{"type":"string","enum":["ingest","serve"]},"scope":{"type":"string","nullable":true},"run_id":{"type":"string","nullable":true},"step":{"type":"string","nullable":true},"producer":{"type":"string","nullable":true},"consumer":{"type":"string","nullable":true},"intent":{"type":"string","nullable":true},"expires_at":{"type":"string","nullable":true,"format":"date-time"},"grace_until":{"type":"string","nullable":true,"format":"date-time"},"max_downloads":{"type":"integer","nullable":true,"minimum":0},"download_count":{"type":"integer","minimum":0},"revoked_at":{"type":"string","nullable":true,"format":"date-time"},"deleted_at":{"type":"string","nullable":true,"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","shortid","agent_link","human_link","sha256","mime","size","filename","direction","scope","run_id","step","producer","consumer","intent","expires_at","grace_until","max_downloads","download_count","revoked_at","deleted_at","created_at"]},"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]},"ReferenceList":{"type":"object","properties":{"files":{"type":"array","items":{"$ref":"#/components/schemas/Reference"}},"cursor":{"type":"string"},"total":{"type":"integer","minimum":0}},"required":["files"]},"RevokeResult":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"revoked_at":{"type":"string","format":"date-time"}},"required":["id","revoked_at"]},"ExtendResult":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"expires_at":{"type":"string","format":"date-time"}},"required":["id","expires_at"]},"ExtendFileBody":{"type":"object","properties":{"expires_in":{"type":"string","enum":["10m","1d","3d","7d","30d"]}},"required":["expires_in"]},"UploadRequest":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"shortid":{"type":"string"},"upload_link":{"type":"string","format":"uri"},"status":{"type":"string","enum":["pending","completed","expired"]},"filename_hint":{"type":"string","nullable":true},"scope":{"type":"string","nullable":true},"run_id":{"type":"string","nullable":true},"step":{"type":"string","nullable":true},"producer":{"type":"string","nullable":true},"consumer":{"type":"string","nullable":true},"intent":{"type":"string","nullable":true},"expires_at":{"type":"string","format":"date-time"},"allowed_mime_types":{"type":"array","nullable":true,"items":{"type":"string"}},"max_file_size_bytes":{"type":"integer","nullable":true,"minimum":0},"upload_count":{"type":"integer","minimum":0},"fulfilled_reference_id":{"type":"string","nullable":true,"format":"uuid"},"created_at":{"type":"string","format":"date-time"}},"required":["id","shortid","upload_link","status","filename_hint","scope","run_id","step","producer","consumer","intent","expires_at","allowed_mime_types","max_file_size_bytes","upload_count","fulfilled_reference_id","created_at"]},"CreateUploadRequestBody":{"type":"object","properties":{"scope":{"type":"string"},"run_id":{"type":"string"},"step":{"type":"string"},"producer":{"type":"string"},"consumer":{"type":"string"},"intent":{"type":"string"},"expires_in":{"type":"string","enum":["10m","1d","3d","7d","30d"]},"filename_hint":{"type":"string"},"allowed_mime_types":{"type":"array","items":{"type":"string"}},"max_file_size_bytes":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["expires_in"]},"UploadRequestWithFile":{"allOf":[{"$ref":"#/components/schemas/UploadRequest"},{"type":"object","properties":{"file":{"$ref":"#/components/schemas/Reference"}}}]},"UploadSubmitForm":{"type":"object","properties":{"file":{"type":"string","format":"binary"}}},"RunManifest":{"type":"object","properties":{"run_id":{"type":"string"},"files":{"type":"array","items":{"$ref":"#/components/schemas/Reference"}},"total":{"type":"integer","minimum":0}},"required":["run_id","files","total"]}},"parameters":{}},"paths":{"/healthz":{"get":{"tags":["ops"],"summary":"Liveness and readiness check","responses":{"200":{"description":"Service is healthy","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"503":{"description":"Service is degraded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthDegraded"}}}}}}},"/v1/files/{id}":{"get":{"tags":["files"],"summary":"Get file metadata","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"File metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Reference"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"File expired, revoked, or deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["files"],"summary":"Soft-delete a file","description":"Sets deleted_at; reference is immediately inaccessible. Blob is retained until reconciliation.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"File soft-deleted"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/files/{id}/download":{"get":{"tags":["files"],"summary":"Download file bytes (agent-facing)","description":"Returns 302 redirect to a presigned URL (S3/R2 backends) or streams bytes (local backend).","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"File bytes (local storage stream)","content":{"application/octet-stream":{"schema":{"nullable":true}}}},"302":{"description":"Redirect to presigned download URL (S3/R2 storage)","headers":{"Location":{"schema":{"type":"string","format":"uri"},"required":true}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"File expired, revoked, or deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/files":{"get":{"tags":["files"],"summary":"List files","parameters":[{"schema":{"type":"string"},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"name":"run_id","in":"query"},{"schema":{"type":"string"},"required":false,"name":"consumer","in":"query"},{"schema":{"type":"string"},"required":false,"name":"intent","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"}],"responses":{"200":{"description":"File list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceList"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/files/{id}/revoke":{"post":{"tags":["files"],"summary":"Revoke a file link","description":"Invalidates the link but retains the blob and other references to it.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"File revoked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeResult"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/files/{id}/erase":{"post":{"tags":["files"],"summary":"Hard-delete a file (GDPR)","description":"Purges the reference row and removes blob bytes from storage if ref_count hits 0. Requires elevated auth (bootstrap token or account-owner session). Not available to guest sessions or scoped API keys.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"204":{"description":"File and bytes erased"},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Insufficient privileges for hard delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/files/{id}/extend":{"post":{"tags":["files"],"summary":"Extend file expiry","description":"Pushes expires_at forward using a preset, subject to plan caps.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtendFileBody"}}}},"responses":{"200":{"description":"Expiry extended","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtendResult"}}}},"400":{"description":"Invalid preset or exceeds plan cap","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/f/{shortid}":{"get":{"tags":["files"],"summary":"Resolve a human short link","description":"Checks expiry, revocation, deletion, password, and max-download limits. Returns 302 redirect (S3/R2) or serves the file (local). Returns 200 HTML page when accessed from a browser without Accept: application/octet-stream.","parameters":[{"schema":{"type":"string"},"required":true,"name":"shortid","in":"path"},{"schema":{"type":"string","description":"Password for protected files"},"required":false,"description":"Password for protected files","name":"x-agentpouch-password","in":"header"}],"responses":{"200":{"description":"File served (local storage stream or HTML download page)","content":{"text/html":{"schema":{"nullable":true}},"application/octet-stream":{"schema":{"nullable":true}}}},"302":{"description":"Redirect to presigned URL (S3/R2 storage)","headers":{"Location":{"schema":{"type":"string","format":"uri"},"required":true}}},"401":{"description":"Password required or incorrect","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"File not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"File expired, revoked, or deleted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/upload-requests":{"post":{"tags":["upload-requests"],"summary":"Create an upload request","description":"Agent creates an upload_link to hand to a human. max_uploads is locked to 1 in v0. Poll GET /v1/upload-requests/:id for completion.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUploadRequestBody"}}}},"responses":{"200":{"description":"Upload request created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadRequest"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/upload-requests/{id}":{"get":{"tags":["upload-requests"],"summary":"Poll upload request status","description":"Returns status (pending | completed | expired) and fulfilled file metadata when completed.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Upload request status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadRequestWithFile"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Upload request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/u/{shortid}":{"get":{"tags":["upload-requests"],"summary":"Human upload page","description":"Server-rendered HTML page for a human to upload a file into an upload request.","parameters":[{"schema":{"type":"string"},"required":true,"name":"shortid","in":"path"}],"responses":{"200":{"description":"Upload form","content":{"text/html":{"schema":{"nullable":true}}}},"404":{"description":"Upload request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Upload request expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["upload-requests"],"summary":"Submit a file to an upload request","description":"Accepts the browser file upload, runs the normal ingest path, and marks the request completed.","parameters":[{"schema":{"type":"string"},"required":true,"name":"shortid","in":"path"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/UploadSubmitForm"}}}},"responses":{"200":{"description":"Upload complete — confirmation page","content":{"text/html":{"schema":{"nullable":true}}}},"400":{"description":"Validation error (file too large, wrong MIME, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Upload request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Upload request expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/runs/{run_id}":{"get":{"tags":["runs"],"summary":"List all artifacts for a run","description":"Returns all references associated with a run_id, across any scope or step.","parameters":[{"schema":{"type":"string"},"required":true,"name":"run_id","in":"path"}],"responses":{"200":{"description":"Run artifact manifest","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunManifest"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}