{"openapi":"3.1.0","info":{"title":"Apex service API","version":"1.5.0","description":"Headless scan lifecycle for organization service keys. See https://ai.cantina.xyz/docs/apex-api."},"servers":[{"url":"https://ai.cantina.xyz"}],"paths":{"/api/apex/v1/credits":{"get":{"operationId":"getApexCreditBalances","summary":"Get organization scan-credit balances","description":"Returns purchased, used, and remaining balances for the service key organization, plus effective availability for each scan type supported by the REST API. This is a point-in-time snapshot; scan creation remains authoritative when requests race or balances change.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"responses":{"200":{"description":"Current organization credit balances","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBalances"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/scans":{"post":{"operationId":"createApexScan","summary":"Start an Apex scan","description":"Accepts a standard, audit, or Lite scan for a connected GitHub commit, or a standard scan from completed local-source archives. If no active workspace is linked to a GitHub repository, Apex creates and links one automatically. By default Apex returns 202 with status preparing, generates an unattended threat model in the background, and starts the paid scan automatically after that threat model completes.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique stable value for one intended scan, scoped to the organization. Reuse it for an identical transport/5xx retry, including after service-key rotation. After correcting a definitive 4xx response, use a new key for the new intended scan.","schema":{"type":"string","minLength":1,"maxLength":255,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScanRequest"}}}},"responses":{"202":{"description":"Scan accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedScan"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"402":{"description":"No scan credits remain","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state. AMBIGUOUS_WORKSPACE includes the matching workspace IDs, prefixes, and names.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true},{"$ref":"#/components/schemas/AmbiguousWorkspaceError"}]}}}},"422":{"description":"Repository type is not supported","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/source-uploads":{"post":{"operationId":"createApexSourceUploads","summary":"Create local-source archive upload sessions","description":"Creates or reuses a tenant-scoped workspace and returns Kernel upload sessions. PUT each tar.gz archive to its returned upload URL, then complete the upload before starting a scan.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSourceUploadsRequest"}}}},"responses":{"200":{"description":"Upload sessions created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceUploadSessions"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Workspace not found in this organization","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/source-uploads/{uploadId}/complete":{"post":{"operationId":"completeApexSourceUpload","summary":"Complete a local-source archive upload","description":"Verifies the uploaded archive and returns the archiveId and sha256 required by a local scanSources entry. Repeating completion is safe.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/UploadId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteSourceUploadRequest"}}}},"responses":{"200":{"description":"Upload verified","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompletedSourceUpload"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Workspace or upload not found","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/scans/{scanId}":{"get":{"operationId":"getApexScan","summary":"Get normalized scan status","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/ScanId"}],"responses":{"200":{"description":"Current scan status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScanStatus"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Scan not found in this organization","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/scans/{scanId}/cancel":{"post":{"operationId":"cancelApexScan","summary":"Cancel an active Apex scan","description":"Cancels remaining scan work. Repeating the request for an already-cancelled scan is safe. Requires the scans:create scope.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/ScanId"}],"responses":{"200":{"description":"Scan cancelled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelledScan"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Scan not found in this organization","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"The scan is already completed or failed, or has not started in Kernel","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/scans/{scanId}/findings":{"get":{"operationId":"getApexScanFindings","summary":"Get completed scan findings as a GitLab SAST report","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/ScanId"}],"responses":{"200":{"description":"GitLab SAST report, including unpublished draft findings for this organization's scan","content":{"application/json":{"schema":{"type":"object","required":["version","vulnerabilities"],"properties":{"version":{"type":"string"},"scan":{"type":"object","additionalProperties":true},"vulnerabilities":{"type":"array","items":{"type":"object","required":["id","name","severity","location"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"severity":{"type":"string"},"location":{"type":"object","additionalProperties":true}},"additionalProperties":true}}},"additionalProperties":true}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Scan not found in this organization","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"The scan has not completed","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"The first terminal findings sync is unavailable or incomplete; retry with Retry-After. Once ready, the persisted report is served without Kernel.","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/workspaces":{"get":{"operationId":"listApexWorkspaces","summary":"List active Apex workspaces","description":"Returns active workspace IDs, prefixes, names, and repositories linked to one GitHub or GitLab repository in the service key organization.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"name":"repository","in":"query","required":true,"description":"Canonical repository URL or owner/name used to filter workspace matches.","schema":{"type":"string","minLength":1,"maxLength":2048}}],"responses":{"200":{"description":"Active workspace summaries","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceList"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}},"/api/apex/v1/workspaces/{workspaceRef}/findings":{"get":{"operationId":"getApexWorkspaceFindings","summary":"Get findings across an active workspace","description":"Resolve a workspace by its human-readable prefix or UUID and return the same non-archived scan set as the workspace findings browser, excluding PR scans, fix-review scans, and unfinished advanced-scan setup drafts. The workspaceRef is scoped to the organization that owns the service key.","security":[{"ApexServiceBearer":[]},{"ApexServiceApiKey":[]}],"parameters":[{"$ref":"#/components/parameters/WorkspaceRef"},{"$ref":"#/components/parameters/FindingState"},{"$ref":"#/components/parameters/Filter"}],"responses":{"200":{"description":"Workspace findings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceFindings"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"401":{"description":"Missing, malformed, expired, or revoked service key","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"403":{"description":"Service key lacks the required scope","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"404":{"description":"Workspace not found in this organization","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"409":{"description":"Request conflicts with current scan or workspace state","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"429":{"description":"Per-key rate limit exceeded","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"500":{"description":"Internal persistence or lookup failure","content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"502":{"description":"Transient provider or Kernel failure; retry the identical request when appropriate","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}},"503":{"description":"A retryable workspace provisioning, Kernel operation, scan finalization, or synchronization failure; for scan creation, retry the identical body with the same Idempotency-Key","headers":{"Retry-After":{"schema":{"type":"integer","minimum":1},"description":"Seconds to wait before retrying when present"}},"content":{"application/json":{"schema":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}}}}},"components":{"securitySchemes":{"ApexServiceBearer":{"type":"http","scheme":"bearer","bearerFormat":"apex_sk_live_…","description":"Organization service key sent as a bearer token."},"ApexServiceApiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Organization service key sent directly in X-API-Key."}},"parameters":{"ScanId":{"name":"scanId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"UploadId":{"name":"uploadId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"WorkspaceRef":{"name":"workspaceRef","in":"path","required":true,"description":"Workspace prefix such as BEDR9, or its UUID.","schema":{"type":"string","minLength":1,"maxLength":128}},"Filter":{"name":"filter","in":"query","required":false,"description":"Repeat to filter findings using the stable workspace UI facets: severity, scan, repo, review, impact, likelihood, status, validation, visibility, duplicate, and source. Status values are proposed, partially_valid, valid, invalid, and duplicate; open is a finding state, not a status. Prefix a filter with ! for is-not, for example !validation:invalid.","style":"form","explode":true,"schema":{"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"FindingState":{"name":"state","in":"query","required":false,"description":"Use open to exclude invalid findings, duplicates, and findings marked fixed, false positive, won't fix, or skipped.","schema":{"type":"string","enum":["all","open"],"default":"all"}}},"schemas":{"CreditBalance":{"type":"object","required":["purchased","used","remaining"],"properties":{"purchased":{"type":"integer","minimum":0},"used":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0}},"additionalProperties":false},"ScanTypeAvailability":{"type":"object","required":["available","ledger","creditsRequired"],"properties":{"available":{"type":"boolean","description":"Whether the current snapshot has enough credits and scans are enabled. Source compatibility must still be checked separately."},"ledger":{"type":"string","enum":["standard","lite"]},"creditsRequired":{"type":"integer","minimum":1}},"additionalProperties":false},"CreditBalances":{"type":"object","required":["companyId","scansEnabled","balances","scanTypes"],"properties":{"companyId":{"type":"string","format":"uuid"},"scansEnabled":{"type":"boolean"},"balances":{"type":"object","required":["standard","lite"],"properties":{"standard":{"$ref":"#/components/schemas/CreditBalance"},"lite":{"$ref":"#/components/schemas/CreditBalance"}},"additionalProperties":false},"scanTypes":{"type":"object","required":["standard","audit","lite"],"properties":{"standard":{"$ref":"#/components/schemas/ScanTypeAvailability"},"audit":{"$ref":"#/components/schemas/ScanTypeAvailability"},"lite":{"$ref":"#/components/schemas/ScanTypeAvailability"}},"additionalProperties":false}},"additionalProperties":false},"CreateScanRequest":{"oneOf":[{"$ref":"#/components/schemas/CreateRemoteScanRequest"},{"$ref":"#/components/schemas/CreateLocalScanRequest"}]},"CreateRemoteScanRequest":{"type":"object","required":["repoUrl","commit"],"additionalProperties":false,"properties":{"repoUrl":{"type":"string","format":"uri","maxLength":2048,"example":"https://github.com/acme/payments"},"commit":{"type":"string","pattern":"^(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$"},"paths":{"type":"array","maxItems":100,"description":"Best-effort focus hints, not a hard repository boundary. Apex may inspect or report code outside these paths.","items":{"type":"string","minLength":1,"maxLength":512}},"workspaceId":{"type":"string","format":"uuid","description":"Required only when more than one active workspace is linked to the repository."},"scanType":{"type":"string","enum":["standard","audit","lite"],"default":"standard","description":"Credit ledger: standard and audit use standard credits (audit requires 2,000), while lite uses one Lite credit when enabled (otherwise the configured standard-ledger credit cost)."},"generateThreatModel":{"type":"boolean","description":"Generate a fresh unattended threat model before reserving scan credits and starting the scan. Explicit true disables implicit existing-model reuse; set false only when intentionally starting without generation or when useExistingThreatModel is true. Defaults to true without workspaceId and false with workspaceId."},"useExistingThreatModel":{"type":"boolean","description":"When workspaceId is provided, defaults to true unless generateThreatModel is explicitly true: validate and reuse that workspace's completed threat model. Requests without workspaceId default to false so a first scan generates a new threat model. Cannot be explicitly combined with generateThreatModel: true."}}},"CreateLocalScanRequest":{"type":"object","required":["workspaceId","scanSources"],"additionalProperties":false,"properties":{"workspaceId":{"type":"string","format":"uuid"},"scanType":{"type":"string","enum":["standard"],"default":"standard","description":"Local archive scans currently support standard scans."},"generateThreatModel":{"type":"boolean","description":"Generate a fresh unattended threat model from these archives before reserving scan credits and starting the scan. Explicit true disables implicit existing-model reuse; otherwise defaults to false for the selected workspace."},"useExistingThreatModel":{"type":"boolean","description":"Defaults to true unless generateThreatModel is explicitly true: validate and reuse the selected workspace's completed threat model instead of generating one from these archives. Cannot be explicitly combined with generateThreatModel: true."},"scanSources":{"type":"array","minItems":1,"maxItems":20,"items":{"$ref":"#/components/schemas/LocalScanSource"}}}},"LocalScanSource":{"type":"object","required":["sourceKind","displayName","relativePath","archiveId","sha256"],"additionalProperties":false,"properties":{"sourceKind":{"type":"string","enum":["local_archive"]},"displayName":{"type":"string","minLength":1,"maxLength":255},"relativePath":{"type":"string","minLength":1,"maxLength":1024},"archiveId":{"type":"string","format":"uuid"},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"},"git":{"$ref":"#/components/schemas/LocalGitMetadata"}}},"LocalGitMetadata":{"type":"object","required":["repoUrl","provider","branch","commitSha","dirty"],"additionalProperties":false,"properties":{"repoUrl":{"type":["string","null"],"format":"uri"},"provider":{"type":["string","null"],"enum":["github","gitlab",null]},"branch":{"type":["string","null"],"maxLength":255},"commitSha":{"type":["string","null"],"maxLength":128},"dirty":{"type":"boolean"}}},"CreateSourceUploadsRequest":{"type":"object","required":["uploads"],"additionalProperties":false,"description":"Provide exactly one of workspaceId or workspaceName.","properties":{"workspaceId":{"type":"string","format":"uuid"},"workspaceName":{"type":"string","minLength":1,"maxLength":200},"uploads":{"type":"array","minItems":1,"maxItems":20,"items":{"$ref":"#/components/schemas/SourceUploadManifest"}}}},"SourceUploadManifest":{"type":"object","required":["displayName","relativePath","archiveFormat","sha256","compressedBytes","uncompressedBytes"],"additionalProperties":false,"properties":{"displayName":{"type":"string","minLength":1,"maxLength":255},"relativePath":{"type":"string","minLength":1,"maxLength":1024},"archiveFormat":{"type":"string","enum":["tar.gz"]},"sha256":{"type":"string","pattern":"^[0-9a-fA-F]{64}$"},"compressedBytes":{"type":"integer","minimum":1,"maximum":524288000},"uncompressedBytes":{"type":"integer","minimum":1,"maximum":2147483648},"git":{"$ref":"#/components/schemas/LocalGitMetadata"}}},"SourceUploadSessions":{"type":"object","required":["workspaceId","workspaceCreated","uploads"],"properties":{"workspaceId":{"type":"string","format":"uuid"},"workspaceCreated":{"type":"boolean"},"uploads":{"type":"array","items":{"type":"object","required":["uploadId","storageProvider","alreadyUploaded"],"properties":{"uploadId":{"type":"string","format":"uuid"},"storageProvider":{"type":"string","enum":["object_store"]},"alreadyUploaded":{"type":"boolean"},"archiveId":{"type":"string","format":"uuid"},"upload":{"type":"object","required":["kind","putUrl","headers"],"properties":{"kind":{"type":"string","enum":["single_part"]},"putUrl":{"type":"string","format":"uri"},"headers":{"type":"object","additionalProperties":{"type":"string"}}},"additionalProperties":false}},"additionalProperties":false}}},"additionalProperties":true},"CompleteSourceUploadRequest":{"type":"object","required":["workspaceId"],"additionalProperties":false,"properties":{"workspaceId":{"type":"string","format":"uuid"}}},"CompletedSourceUpload":{"type":"object","required":["workspaceId","uploadId","archiveId","sha256"],"properties":{"workspaceId":{"type":"string","format":"uuid"},"uploadId":{"type":"string"},"archiveId":{"type":"string","format":"uuid"},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$"}},"additionalProperties":true},"AcceptedScan":{"type":"object","required":["scanId","status","statusUrl","findingsUrl"],"properties":{"scanId":{"type":"string","format":"uuid"},"workspaceId":{"type":"string","format":"uuid","description":"Resolved workspace ID. An idempotent replay while preparation is still active may omit this field."},"status":{"type":"string","enum":["preparing","queued","running","completed","failed","cancelled"]},"statusUrl":{"type":"string"},"findingsUrl":{"type":"string"}},"additionalProperties":false},"ScanStatus":{"type":"object","required":["scanId","status","progress","createdAt","updatedAt"],"properties":{"scanId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["preparing","queued","running","completed","failed","cancelled"]},"progress":{"type":"number","minimum":0,"maximum":100},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"error":{"type":"string","description":"Present when deferred preparation fails."},"code":{"type":"string","description":"Stable error code when deferred preparation fails."}},"additionalProperties":false},"CancelledScan":{"type":"object","required":["scanId","status","statusUrl"],"properties":{"scanId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["cancelled"]},"statusUrl":{"type":"string"}},"additionalProperties":false},"WorkspaceFindings":{"type":"object","required":["workspace","scans","findings","filters","state"],"properties":{"workspace":{"$ref":"#/components/schemas/WorkspaceSummary"},"scans":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceScan"}},"findings":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceFinding"}},"filters":{"type":"array","description":"Filters applied to this response, in canonical form.","items":{"type":"string"}},"state":{"type":"string","enum":["all","open"],"description":"The finding lifecycle state applied to this response."}},"additionalProperties":false},"WorkspaceList":{"type":"object","required":["workspaces"],"properties":{"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceListItem"}}},"additionalProperties":false},"AmbiguousWorkspaceError":{"type":"object","required":["error","code","repository","workspaces","resolution"],"properties":{"error":{"type":"string"},"code":{"type":"string","const":"AMBIGUOUS_WORKSPACE"},"repository":{"type":"string"},"workspaces":{"type":"array","minItems":2,"items":{"$ref":"#/components/schemas/WorkspaceSummary"}},"resolution":{"type":"string"}},"additionalProperties":false},"WorkspaceListItem":{"type":"object","required":["workspaceId","prefix","name","repositories"],"properties":{"workspaceId":{"type":"string","format":"uuid"},"prefix":{"type":["string","null"]},"name":{"type":"string"},"repositories":{"type":"array","items":{"type":"object","required":["provider","fullName"],"properties":{"provider":{"type":"string","enum":["github","gitlab"]},"fullName":{"type":"string"}},"additionalProperties":false}}},"additionalProperties":false},"WorkspaceSummary":{"type":"object","required":["workspaceId","prefix","name"],"properties":{"workspaceId":{"type":"string","format":"uuid"},"prefix":{"type":["string","null"]},"name":{"type":"string"}},"additionalProperties":false},"WorkspaceScan":{"type":"object","required":["scanId","displayName","sequenceNumber","status","createdAt","updatedAt"],"properties":{"scanId":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"sequenceNumber":{"type":["integer","null"]},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"additionalProperties":false},"WorkspaceFinding":{"type":"object","required":["id","findingIdentifier","scanId","title","description","severity","impact","likelihood","status","visibility","reviewState","isDuplicate","duplicateOfId","repository","sourceFile","validation","validity","createdAt","updatedAt","findingUrl"],"properties":{"id":{"type":"string","format":"uuid"},"findingIdentifier":{"type":["string","null"]},"scanId":{"type":["string","null"],"format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"severity":{"type":"string","enum":["extreme","critical","high","medium","low","informational"]},"impact":{"type":"string","enum":["critical","high","medium","low"]},"likelihood":{"type":"string","enum":["high","medium","low"]},"status":{"type":"string","enum":["proposed","partially_valid","valid","invalid","duplicate"]},"visibility":{"type":"string","enum":["draft","public"]},"reviewState":{"type":"string","enum":["unreviewed","in_review","accepted","pending_merge","false_positive","wont_fix","skipped","marked_fixed"]},"isDuplicate":{"type":"boolean"},"duplicateOfId":{"type":["string","null"],"format":"uuid"},"repository":{"type":"string","description":"Repository label used by the workspace findings UI."},"sourceFile":{"type":"string","description":"Primary source-file label used by the workspace findings UI."},"validation":{"anyOf":[{"$ref":"#/components/schemas/WorkspaceFindingValidation"},{"type":"null"}]},"validity":{"type":"string","enum":["valid","invalid","unknown"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"findingUrl":{"type":"string"}},"additionalProperties":false},"WorkspaceFindingValidation":{"type":"object","required":["decision","analysis","severity"],"properties":{"decision":{"type":"string","enum":["valid","invalid","partially-valid"]},"analysis":{"type":["string","null"]},"severity":{"type":["string","null"],"enum":["extreme","critical","high","medium","low","informational",null]}},"additionalProperties":false},"Error":{"type":"object","required":["error","code"],"properties":{"error":{"type":"string"},"code":{"type":"string"}},"additionalProperties":true}}}}