{"openapi":"3.1.0","info":{"title":"Plurall AI API","version":"2026-05-06","description":"Authenticated Plurall AI staging API for media scans, cases, and signed webhook delivery."},"servers":[{"url":"https://plurall.tech"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Scans","description":"Private media ingestion and verdict retrieval."},{"name":"Cases","description":"Investigation workflows linked to scans."},{"name":"Webhooks","description":"Signed event delivery and retry visibility."}],"paths":{"/api/v1/scans/upload-intents":{"post":{"operationId":"createScanUploadIntent","summary":"Create a scan upload intent","description":"Creates a tenant-scoped scan record and returns a short-lived direct-upload target for private media ingestion.","tags":["Scans"],"security":[{"bearerAuth":["scans:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanUploadIntentRequest"},"example":{"fileName":"clip.mp4","contentType":"video/mp4","mediaType":"video","byteSize":1048576}}}},"responses":{"201":{"description":"Upload intent created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanUploadIntentResponse"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/scans/{scanId}/upload-complete":{"post":{"operationId":"completeScanUpload","summary":"Complete a scan upload","description":"Marks an uploaded media object complete and creates a deterministic staging verdict while the production inference worker path is being hardened.","tags":["Scans"],"security":[{"bearerAuth":["scans:write"]}],"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string"},"description":"Scan identifier returned by the upload intent."}],"responses":{"200":{"description":"Scan completed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/scans":{"get":{"operationId":"listScans","summary":"List scans","description":"Returns paginated scans for the organization derived from the bearer API key.","tags":["Scans"],"security":[{"bearerAuth":["scans:read"]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor returned in `meta.nextCursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Maximum items to return."}],"responses":{"200":{"description":"Paginated scans.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanList"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/scans/{scanId}":{"get":{"operationId":"getScan","summary":"Get a scan","description":"Fetches one scan if it belongs to the API key's organization.","tags":["Scans"],"security":[{"bearerAuth":["scans:read"]}],"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string"},"description":"Scan identifier."}],"responses":{"200":{"description":"Scan result.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Scan"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/scans/{scanId}/job":{"get":{"operationId":"getScanJob","summary":"Get scan job status","description":"Returns async scan-job status and retry guidance for polling clients.","tags":["Scans"],"security":[{"bearerAuth":["scans:read"]}],"parameters":[{"name":"scanId","in":"path","required":true,"schema":{"type":"string"},"description":"Scan identifier."}],"responses":{"200":{"description":"Scan job status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanJob"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/cases":{"post":{"operationId":"createCase","summary":"Create a case","description":"Creates a persisted investigation case from one or more scans in the API key's organization.","tags":["Cases"],"security":[{"bearerAuth":["cases:write"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseCreateRequest"},"example":{"title":"Executive impersonation review","scanIds":["scan_123"],"severity":"high"}}}},"responses":{"201":{"description":"Case created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Case"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"get":{"operationId":"listCases","summary":"List cases","description":"Returns paginated cases for the organization derived from the bearer API key.","tags":["Cases"],"security":[{"bearerAuth":["cases:read"]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor returned in `meta.nextCursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Maximum items to return."}],"responses":{"200":{"description":"Paginated cases.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseList"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/cases/{caseId}":{"get":{"operationId":"getCase","summary":"Get a case","description":"Fetches a case if it belongs to the API key's organization.","tags":["Cases"],"security":[{"bearerAuth":["cases:read"]}],"parameters":[{"name":"caseId","in":"path","required":true,"schema":{"type":"string"},"description":"Case identifier."}],"responses":{"200":{"description":"Case detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Case"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/webhooks":{"post":{"operationId":"createWebhookEndpoint","summary":"Create a webhook endpoint","description":"Registers an HTTPS endpoint and returns its signing secret once. Encrypted secret material is never returned in API responses.","tags":["Webhooks"],"security":[{"bearerAuth":["webhooks:manage"]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreateRequest"},"example":{"url":"https://example.com/plurall/webhooks","description":"Production intake","events":["scan.completed","verdict.synthetic"]}}}},"responses":{"201":{"description":"Webhook endpoint created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookIssueResponse"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}},"get":{"operationId":"listWebhookEndpoints","summary":"List webhook endpoints","description":"Returns public endpoint metadata and delivery success rates.","tags":["Webhooks"],"security":[{"bearerAuth":["webhooks:manage"]}],"parameters":[{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor returned in `meta.nextCursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Maximum items to return."}],"responses":{"200":{"description":"Paginated webhooks.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpointList"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/webhooks/{webhookId}/status":{"post":{"operationId":"updateWebhookStatus","summary":"Pause, activate, or revoke a webhook","description":"Updates delivery status for one webhook endpoint owned by the API key's organization.","tags":["Webhooks"],"security":[{"bearerAuth":["webhooks:manage"]}],"parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook endpoint identifier."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookStatusRequest"},"example":{"status":"paused"}}}},"responses":{"200":{"description":"Webhook status updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEndpoint"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/webhooks/{webhookId}/test":{"post":{"operationId":"testWebhookEndpoint","summary":"Send a signed test event","description":"Creates a signed test delivery for an endpoint and records the response.","tags":["Webhooks"],"security":[{"bearerAuth":["webhooks:manage"]}],"parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"},"description":"Webhook endpoint identifier."}],"responses":{"202":{"description":"Test delivery attempted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDelivery"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/api/v1/webhooks/deliveries":{"get":{"operationId":"listWebhookDeliveries","summary":"List webhook deliveries","description":"Returns signed delivery attempts, response codes, and retry state.","tags":["Webhooks"],"security":[{"bearerAuth":["webhooks:manage"]}],"parameters":[{"name":"webhookId","in":"query","schema":{"type":"string"},"description":"Optional endpoint filter."},{"name":"cursor","in":"query","schema":{"type":"string"},"description":"Opaque pagination cursor returned in `meta.nextCursor`."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"description":"Maximum items to return."}],"responses":{"200":{"description":"Paginated webhook deliveries.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookDeliveryList"}}}},"401":{"description":"Missing, malformed, or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"403":{"description":"The API key is valid but missing the required scope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"The API key or organization exceeded its active rate-limit bucket.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds until this request should be retried."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Active rate-limit bucket size."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Remaining requests in the active bucket."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Unix epoch seconds when the active bucket resets."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Plurall AI API key"}},"schemas":{"ErrorEnvelope":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","requestId"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"requestId":{"type":"string"}}}}},"ScanUploadIntentRequest":{"type":"object","required":["fileName","contentType","mediaType","byteSize"],"properties":{"fileName":{"type":"string"},"contentType":{"type":"string"},"mediaType":{"type":"string","enum":["image","video","audio","document"]},"byteSize":{"type":"integer","minimum":1}}},"ScanUploadIntentResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/ScanUploadIntent"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"ScanUploadIntent":{"type":"object","required":["scanId","uploadUrl","uploadHeaders"],"properties":{"scanId":{"type":"string"},"uploadUrl":{"type":"string"},"uploadHeaders":{"type":"object","additionalProperties":{"type":"string"}},"expiresAt":{"type":"string","format":"date-time"}}},"Scan":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/ScanData"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"ScanList":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/ScanData"}},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"ScanData":{"type":"object","required":["id","organizationId","status","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"fileName":{"type":"string"},"mediaType":{"type":"string"},"status":{"type":"string","enum":["queued","uploading","processing","complete","failed"]},"verdict":{"type":["string","null"],"enum":["authentic","suspicious","synthetic",null]},"confidence":{"type":["number","null"],"minimum":0,"maximum":1},"riskLevel":{"type":["string","null"],"enum":["low","medium","high","critical",null]},"modelVersion":{"type":["string","null"]},"pipelineVersion":{"type":["string","null"]},"signals":{"type":"object","additionalProperties":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"ScanJob":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/ScanJobData"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"ScanJobData":{"type":"object","properties":{"scanId":{"type":"string"},"status":{"type":"string"},"nextPollAfter":{"type":"string","format":"date-time"}}},"CaseCreateRequest":{"type":"object","required":["title","scanIds"],"properties":{"title":{"type":"string"},"scanIds":{"type":"array","items":{"type":"string"},"minItems":1},"severity":{"type":"string","enum":["low","medium","high","critical"]},"assignee":{"type":"string"}}},"Case":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/CaseData"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"CaseList":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CaseData"}},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"CaseData":{"type":"object","required":["id","organizationId","title","status","severity","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"title":{"type":"string"},"scanIds":{"type":"array","items":{"type":"string"}},"status":{"type":"string"},"severity":{"type":"string"},"verdict":{"type":["string","null"]},"assignee":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"WebhookCreateRequest":{"type":"object","required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"description":{"type":"string"},"events":{"type":"array","items":{"type":"string","enum":["scan.created","scan.completed","verdict.synthetic","verdict.suspicious","case.opened","case.escalated","case.resolved","user.flagged","report.ready","verification.completed"]}}}},"WebhookIssueResponse":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/WebhookIssueData"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"WebhookIssueData":{"type":"object","required":["endpoint","secret"],"properties":{"endpoint":{"$ref":"#/components/schemas/WebhookEndpointData"},"secret":{"type":"string","example":"whsec_..."}}},"WebhookEndpoint":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/WebhookEndpointData"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"WebhookEndpointList":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpointData"}},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"WebhookEndpointData":{"type":"object","required":["id","organizationId","url","events","status","secretMasked"],"properties":{"id":{"type":"string"},"organizationId":{"type":"string"},"url":{"type":"string"},"description":{"type":"string"},"events":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["active","paused","revoked"]},"secretMasked":{"type":"string"},"successRate":{"type":"number"},"lastDeliveryAt":{"type":"string","format":"date-time"}}},"WebhookStatusRequest":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["active","paused","revoked"]}}},"WebhookDelivery":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/WebhookDeliveryData"},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"WebhookDeliveryList":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookDeliveryData"}},"meta":{"type":"object","required":["requestId","timestamp","apiVersion"],"properties":{"requestId":{"type":"string"},"timestamp":{"type":"string","format":"date-time"},"apiVersion":{"type":"string","example":"2026-05-06"},"nextCursor":{"type":["string","null"]}}}}},"WebhookDeliveryData":{"type":"object","required":["id","webhookId","event","status","attempts","signatureHeader"],"properties":{"id":{"type":"string"},"webhookId":{"type":"string"},"event":{"type":"string"},"status":{"type":"string","enum":["pending","retrying","succeeded","failed"]},"attempts":{"type":"integer"},"maxAttempts":{"type":"integer"},"nextAttemptAt":{"type":["string","null"],"format":"date-time"},"responseCode":{"type":["integer","null"]},"signatureHeader":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}}}}}