{"openapi":"3.1.0","info":{"title":"ComplyHub API","version":"1.0.0","description":"Programmatic access to the ComplyHub GRC platform. All `/api/v1` endpoints are organization-scoped and enforce the same RBAC and row-level tenant isolation as the web application. Authenticate with a bearer API key (`Authorization: Bearer chk_…`) or, for same-origin browser calls, the session cookie. Errors use RFC 9457 `application/problem+json`."},"servers":[{"url":"http://complyhub.persol-enterprise.com"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"chk_*","description":"A ComplyHub API key. Create one under Admin → Settings → API keys."},"cookieAuth":{"type":"apiKey","in":"cookie","name":"ch_session","description":"Interactive session cookie (same-origin only)."}},"schemas":{"Problem":{"type":"object","description":"RFC 9457 problem document.","properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"},"errors":{"type":"object","additionalProperties":true,"description":"Field-level validation issues, when applicable."}},"required":["type","title","status"]}}},"security":[{"bearerAuth":[]},{"cookieAuth":[]}],"tags":[{"name":"meta"},{"name":"identity"},{"name":"dashboard"},{"name":"frameworks"},{"name":"requirements"},{"name":"controls"},{"name":"risks"},{"name":"evidence"},{"name":"tasks"},{"name":"vendors"},{"name":"reports"}],"paths":{"/api/v1/me":{"get":{"summary":"The authenticated principal, its organization and effective permissions.","tags":["identity"],"operationId":"get_api_v1_me","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/api/v1/dashboard":{"get":{"summary":"Aggregated compliance posture for the organization.","tags":["dashboard"],"operationId":"get_api_v1_dashboard","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `framework:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role."}},"/api/v1/frameworks":{"get":{"summary":"List compliance frameworks with rolled-up requirement/evidence counts.","tags":["frameworks"],"operationId":"get_api_v1_frameworks","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `framework:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role."}},"/api/v1/frameworks/{id}":{"get":{"summary":"Get one framework by id.","tags":["frameworks"],"operationId":"get_api_v1_frameworks_id","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `framework:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/v1/requirements":{"get":{"summary":"List requirements. Filter by framework, status, priority, owner, free text.","tags":["requirements"],"operationId":"get_api_v1_requirements","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `framework:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"page","in":"query","required":true,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":true,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"frameworkId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","maxLength":40}},{"name":"priority","in":"query","required":false,"schema":{"type":"string","maxLength":40}},{"name":"ownerId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}]}},"/api/v1/requirements/{id}":{"get":{"summary":"Get one requirement by id.","tags":["requirements"],"operationId":"get_api_v1_requirements_id","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `framework:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/v1/controls":{"get":{"summary":"List controls with mapping and testing metadata.","tags":["controls"],"operationId":"get_api_v1_controls","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `control:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"page","in":"query","required":true,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":true,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"category","in":"query","required":false,"schema":{"type":"string","maxLength":60}},{"name":"frequency","in":"query","required":false,"schema":{"type":"string","maxLength":40}},{"name":"effectiveness","in":"query","required":false,"schema":{"type":"string","maxLength":40}}]}},"/api/v1/controls/{id}":{"get":{"summary":"Get one control by id.","tags":["controls"],"operationId":"get_api_v1_controls_id","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `control:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/v1/risks":{"get":{"summary":"List risks in the register.","tags":["risks"],"operationId":"get_api_v1_risks","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `risk:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"page","in":"query","required":true,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":true,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"severity","in":"query","required":false,"schema":{"type":"string","maxLength":20}},{"name":"status","in":"query","required":false,"schema":{"type":"string","maxLength":30}},{"name":"treatment","in":"query","required":false,"schema":{"type":"string","maxLength":30}},{"name":"ownerId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"frameworkId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}}]}},"/api/v1/risks/{id}":{"get":{"summary":"Get one risk by id.","tags":["risks"],"operationId":"get_api_v1_risks_id","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `risk:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/v1/evidence":{"get":{"summary":"List evidence records.","tags":["evidence"],"operationId":"get_api_v1_evidence","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `evidence:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"page","in":"query","required":true,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":true,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"type":"string","maxLength":30}},{"name":"frameworkId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"evidenceType","in":"query","required":false,"schema":{"type":"string","maxLength":40}},{"name":"source","in":"query","required":false,"schema":{"type":"string","maxLength":40}}]}},"/api/v1/evidence/{id}":{"get":{"summary":"Get one evidence record by id.","tags":["evidence"],"operationId":"get_api_v1_evidence_id","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `evidence:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/v1/tasks":{"get":{"summary":"List tasks / actions.","tags":["tasks"],"operationId":"get_api_v1_tasks","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `task:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"page","in":"query","required":true,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":true,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"status","in":"query","required":false,"schema":{"type":"string","maxLength":30}},{"name":"priority","in":"query","required":false,"schema":{"type":"string","maxLength":20}},{"name":"assigneeId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"frameworkId","in":"query","required":false,"schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"}},{"name":"bucket","in":"query","required":false,"schema":{"type":"string","enum":["overdue","due_soon","on_track"]}}]}},"/api/v1/vendors":{"get":{"summary":"List third-party vendors.","tags":["vendors"],"operationId":"get_api_v1_vendors","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `risk:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"page","in":"query","required":true,"schema":{"default":1,"type":"integer","minimum":1,"maximum":9007199254740991}},{"name":"pageSize","in":"query","required":true,"schema":{"default":25,"type":"integer","minimum":1,"maximum":100}},{"name":"q","in":"query","required":false,"schema":{"type":"string","maxLength":200}},{"name":"tier","in":"query","required":false,"schema":{"type":"string","maxLength":20}},{"name":"dataHandled","in":"query","required":false,"schema":{"type":"string","maxLength":60}},{"name":"status","in":"query","required":false,"schema":{"type":"string","maxLength":30}}]}},"/api/v1/reports":{"get":{"summary":"List report definitions and recently generated reports.","tags":["reports"],"operationId":"get_api_v1_reports","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `report:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role."},"post":{"summary":"Generate a report from a definition. Returns the generated-report id.","tags":["reports"],"operationId":"post_api_v1_reports","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"201":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `report:generate` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"definitionId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"format":{"default":"pdf","type":"string","enum":["csv","json","pdf","xlsx"]}},"required":["definitionId","format"],"additionalProperties":false}}}}}},"/api/v1/reports/{id}/download":{"get":{"summary":"Download a generated report as its stored bytes.","tags":["reports"],"operationId":"get_api_v1_reports_id_download","security":[{"bearerAuth":[]},{"cookieAuth":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Validation failed","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing or invalid credentials","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"403":{"description":"Insufficient permission scope","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"404":{"description":"Not found (or not visible to this tenant)","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"500":{"description":"Unexpected error","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}},"description":"Requires the `report:read` permission. For API keys the effective permission set is the key's scopes intersected with the owning user's role.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/health":{"get":{"summary":"Liveness probe with a database round-trip.","tags":["meta"],"operationId":"get_health","security":[],"responses":{"200":{"description":"Service healthy"},"503":{"description":"A dependency is down"}}}}}}