{"openapi":"3.1.0","info":{"title":"Sourcery API","description":"Public REST API for security scanning. Authenticate with an API key issued from the Sourcery dashboard.","version":"0.1.0"},"servers":[{"url":"/api"}],"paths":{"/v1/security-issue-groups":{"get":{"tags":["Security issue groups"],"summary":"List security issue groups","description":"Returns a page of grouped security issues scoped to the authenticated account. Pass `next_cursor` from the response back as `cursor` to fetch the next page. Filters combine with AND semantics.","operationId":"list_security_issue_groups_v1_security_issue_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter by repository ids.","title":"Repository Ids"},"description":"Filter by repository ids."},{"name":"issue_types","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/SecurityIssueTypeName"}},{"type":"null"}],"description":"Filter by issue type.","title":"Issue Types"},"description":"Filter by issue type."},{"name":"statuses","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/SecurityStatus"}},{"type":"null"}],"description":"Filter by issue status.","title":"Statuses"},"description":"Filter by issue status."},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on title / file / package.","title":"Search"},"description":"Substring match on title / file / package."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque pagination token from a previous `next_cursor`.","title":"Cursor"},"description":"Opaque pagination token from a previous `next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of objects to return.","default":20,"title":"Limit"},"description":"Maximum number of objects to return."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse_SecurityIssueGroupResponse_"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Security issue groups"],"summary":"Bulk-update security issue groups","description":"Update `status` and/or `severity_override` on a list of groups. At least one of the two must be provided. Setting `status` applies to every issue in each group. Setting `status` to `SNOOZED` requires `snoozed_until` (ISO-8601 UTC); other target statuses must omit `snoozed_until`. `SOLVED` is excluded from the request enum because the scanner sets it automatically — but issues currently in `SOLVED` can still be transitioned to other statuses. The response splits inputs into `updated_ids` (groups with at least one modified issue) and `failed` (with a reason per id).","operationId":"bulk_update_security_issue_groups_v1_security_issue_groups_patch","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateGroupsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateGroupsResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/security-issue-groups/stats":{"get":{"tags":["Security issue groups"],"summary":"Aggregate counts across security issue groups","description":"Returns counts of groups bucketed by status and severity, scoped to the authenticated account. A group counts toward each status bucket if any of its issues are in that status.","operationId":"get_security_issue_group_stats_v1_security_issue_groups_stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Repository Ids"}},{"name":"issue_types","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/SecurityIssueTypeName"}},{"type":"null"}],"title":"Issue Types"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityStats"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/security-issue-groups/{security_issue_group_id}":{"get":{"tags":["Security issue groups"],"summary":"Fetch a single security issue group","description":"Returns the group with its member issues. `404 not_found` if the id doesn't exist or belongs to another account.","operationId":"get_security_issue_group_v1_security_issue_groups__security_issue_group_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"security_issue_group_id","in":"path","required":true,"schema":{"type":"integer","title":"Security Issue Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityIssueGroupDetailResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/security-issues":{"get":{"tags":["Security issues"],"summary":"List security issues","description":"Returns a page of security issues scoped to the authenticated account. Pass `next_cursor` from the response back as `cursor` to fetch the next page. Filters combine with AND semantics.","operationId":"list_security_issues_v1_security_issues_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"description":"Filter by repository ids.","title":"Repository Ids"},"description":"Filter by repository ids."},{"name":"issue_types","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/SecurityIssueTypeName"}},{"type":"null"}],"description":"Filter by issue type.","title":"Issue Types"},"description":"Filter by issue type."},{"name":"statuses","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/SecurityStatus"}},{"type":"null"}],"description":"Filter by issue status.","title":"Statuses"},"description":"Filter by issue status."},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Substring match on title / file / package.","title":"Search"},"description":"Substring match on title / file / package."},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque pagination token from a previous `next_cursor`.","title":"Cursor"},"description":"Opaque pagination token from a previous `next_cursor`."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of objects to return.","default":20,"title":"Limit"},"description":"Maximum number of objects to return."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListResponse_SecurityIssueResponse_"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Security issues"],"summary":"Bulk-update security issues","description":"Update `status` and/or `severity_override` on a list of issues. At least one of the two must be provided. Setting `status` to `SNOOZED` requires `snoozed_until` (ISO-8601 UTC); other target statuses must omit `snoozed_until`. `SOLVED` is excluded from the request enum because the scanner sets it automatically when a scan no longer detects the issue — but issues currently in `SOLVED` can still be transitioned to other statuses (e.g. to permanently `IGNORED`). The response splits inputs into `updated_ids` (modified) and `failed` (with a reason per id).","operationId":"bulk_update_security_issues_v1_security_issues_patch","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateIssuesRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkUpdateIssuesResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/security-issues/stats":{"get":{"tags":["Security issues"],"summary":"Aggregate counts across security issues","description":"Returns counts of issues bucketed by status and severity, scoped to the authenticated account. Severity buckets count active issues only — see the `SecurityStats` description for how counts relate.","operationId":"get_security_issue_stats_v1_security_issues_stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repository_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Repository Ids"}},{"name":"issue_types","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/SecurityIssueTypeName"}},{"type":"null"}],"title":"Issue Types"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityStats"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/security-issues/{security_issue_id}":{"get":{"tags":["Security issues"],"summary":"Fetch a single security issue","description":"Returns the full record for one issue. `404 not_found` if the id doesn't exist or belongs to another account.","operationId":"get_security_issue_v1_security_issues__security_issue_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"security_issue_id","in":"path","required":true,"schema":{"type":"integer","title":"Security Issue Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityIssueResponse"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Schema validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"components":{"schemas":{"ApiErrorType":{"type":"string","enum":["invalid_request_error","validation_error","authentication_error","permission_error","not_found","rate_limit_error","internal_error"],"title":"ApiErrorType","description":"Categories of error returned in the Stripe-style envelope.\n\nCustomers branch on `error.type` for retry / alerting / surfacing\nbehaviour. Mirrors the (small) set of error families Stripe uses so\nSDK consumers get exhaustive switch coverage without inventing custom\ndiscriminators per status code."},"BulkUpdateGroupsRequest":{"properties":{"ids":{"items":{"type":"integer"},"type":"array","maxItems":100,"minItems":1,"title":"Ids"},"status":{"anyOf":[{"$ref":"#/components/schemas/SecurityStatusInput"},{"type":"null"}]},"snoozed_until":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-04-28T12:34:56Z"]},{"type":"null"}],"title":"Snoozed Until"},"severity_override":{"anyOf":[{"$ref":"#/components/schemas/SecuritySeverityName"},{"type":"null"}]},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","required":["ids"],"title":"BulkUpdateGroupsRequest"},"BulkUpdateGroupsResponse":{"properties":{"updated_ids":{"items":{"type":"integer"},"type":"array","title":"Updated Ids"},"failed":{"items":{"$ref":"#/components/schemas/FailedUpdate"},"type":"array","title":"Failed"}},"additionalProperties":false,"type":"object","required":["updated_ids","failed"],"title":"BulkUpdateGroupsResponse","description":"Result of a bulk update.\n\n`updated_ids` lists groups where at least one issue was modified.\n`failed` covers every other input id with a reason — `not_found`\n(unknown id or another account's id, deliberately collapsed) or\n`not_eligible` (every issue in the group is already in the target state)."},"BulkUpdateIssuesRequest":{"properties":{"ids":{"items":{"type":"integer"},"type":"array","maxItems":100,"minItems":1,"title":"Ids"},"status":{"anyOf":[{"$ref":"#/components/schemas/SecurityStatusInput"},{"type":"null"}]},"snoozed_until":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-04-28T12:34:56Z"]},{"type":"null"}],"title":"Snoozed Until"},"severity_override":{"anyOf":[{"$ref":"#/components/schemas/SecuritySeverityName"},{"type":"null"}]},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","required":["ids"],"title":"BulkUpdateIssuesRequest"},"BulkUpdateIssuesResponse":{"properties":{"updated_ids":{"items":{"type":"integer"},"type":"array","title":"Updated Ids"},"failed":{"items":{"$ref":"#/components/schemas/FailedUpdate"},"type":"array","title":"Failed"}},"additionalProperties":false,"type":"object","required":["updated_ids","failed"],"title":"BulkUpdateIssuesResponse","description":"Result of a bulk update.\n\n`updated_ids` lists the issues that were modified. `failed` covers every\nother input id with a reason — `not_found` (unknown id or another\naccount's id, deliberately collapsed) or `not_eligible` (already in the\ntarget state, or `SOLVED` and immutable)."},"DependencyEdgeResponse":{"properties":{"from_package":{"type":"string","title":"From Package"},"to_package":{"type":"string","title":"To Package"}},"additionalProperties":false,"type":"object","required":["from_package","to_package"],"title":"DependencyEdgeResponse","description":"A dependency edge — `from_package` depends on `to_package`."},"DependencyGraphResponse":{"properties":{"nodes":{"items":{"$ref":"#/components/schemas/DependencyNodeResponse"},"type":"array","title":"Nodes"},"edges":{"items":{"$ref":"#/components/schemas/DependencyEdgeResponse"},"type":"array","title":"Edges"}},"additionalProperties":false,"type":"object","required":["nodes","edges"],"title":"DependencyGraphResponse","description":"Resolved dependency graph for a `DEPENDENCY` issue.\n\nThe chain from a project's root package to the vulnerable dependency.\n`null` for non-dependency findings or when the scanner couldn't resolve\nthe graph."},"DependencyNodeResponse":{"properties":{"name":{"type":"string","title":"Name"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"relationship":{"type":"string","title":"Relationship","description":"`root`, `workspace`, `direct`, or `indirect` (transitive)."},"vulnerable":{"type":"boolean","title":"Vulnerable","description":"True if this node is the vulnerable package being reported."},"dev":{"type":"boolean","title":"Dev","description":"True for dev/test-only dependencies."}},"additionalProperties":false,"type":"object","required":["name","version","relationship","vulnerable","dev"],"title":"DependencyNodeResponse","description":"A package in the dependency graph for a vulnerable dependency."},"ErrorBody":{"properties":{"type":{"$ref":"#/components/schemas/ApiErrorType"},"message":{"type":"string","title":"Message"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"param":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Param"}},"additionalProperties":false,"type":"object","required":["type","message"],"title":"ErrorBody"},"ErrorResponse":{"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"additionalProperties":false,"type":"object","required":["error"],"title":"ErrorResponse","description":"Stripe-style error envelope returned for every non-2xx response."},"FailedUpdate":{"properties":{"id":{"type":"integer","title":"Id"},"reason":{"$ref":"#/components/schemas/FailedUpdateReason"}},"additionalProperties":false,"type":"object","required":["id","reason"],"title":"FailedUpdate","description":"An id from a bulk PATCH input that did not get updated.\n\n`not_found` covers ids that don't exist or belong to another account\n(the two are deliberately collapsed to avoid leaking existence across\ntenants). `not_eligible` covers ids that exist within the account but\ndidn't transition — most commonly because the request was a no-op\n(e.g. PATCHing an already-`ACTIVE` issue to `ACTIVE`). PATCHes to\n`IGNORED` / `SNOOZED` are idempotent and always land in `updated_ids`,\neven when the issue is already in that state."},"FailedUpdateReason":{"type":"string","enum":["not_found","not_eligible"],"title":"FailedUpdateReason","description":"Why a particular id wasn't updated by a bulk PATCH."},"IssueCounts":{"properties":{"total_count":{"type":"integer","title":"Total Count"},"active_count":{"type":"integer","title":"Active Count"},"snoozed_count":{"type":"integer","title":"Snoozed Count"},"ignored_count":{"type":"integer","title":"Ignored Count"},"solved_count":{"type":"integer","title":"Solved Count"}},"additionalProperties":false,"type":"object","required":["total_count","active_count","snoozed_count","ignored_count","solved_count"],"title":"IssueCounts","description":"Per-status issue counts within a group.\n\nField names match the ``*_count`` suffix used on top-level\n``SecurityStats`` for consistency."},"IssueTrackerTaskSummary":{"properties":{"tracker_type":{"$ref":"#/components/schemas/IssueTrackerType"},"id":{"type":"string","title":"Id","description":"External tracker id (e.g. `SEC-123`)."},"url":{"type":"string","title":"Url"},"title":{"type":"string","title":"Title","description":"Tracker task title (subject)."}},"additionalProperties":false,"type":"object","required":["tracker_type","id","url","title"],"title":"IssueTrackerTaskSummary","description":"The external tracker task linked to a security issue group."},"IssueTrackerType":{"type":"string","enum":["JIRA","LINEAR","GITHUB","GITLAB"],"title":"IssueTrackerType"},"ListResponse_SecurityIssueGroupResponse_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SecurityIssueGroupResponse"},"type":"array","title":"Data"},"has_more":{"type":"boolean","title":"Has More"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"additionalProperties":false,"type":"object","required":["data","has_more"],"title":"ListResponse[SecurityIssueGroupResponse]"},"ListResponse_SecurityIssueResponse_":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SecurityIssueResponse"},"type":"array","title":"Data"},"has_more":{"type":"boolean","title":"Has More"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"additionalProperties":false,"type":"object","required":["data","has_more"],"title":"ListResponse[SecurityIssueResponse]"},"SecurityIssueGroupDetailResponse":{"properties":{"id":{"type":"integer","title":"Id"},"title":{"type":"string","title":"Title","description":"Best human-readable title for the group. The scanner's group title where available; falls back to the package name (`DEPENDENCY`/`LICENSE`) or the first issue's title."},"repository_id":{"type":"integer","title":"Repository Id"},"repository_name":{"type":"string","title":"Repository Name"},"issue_type":{"$ref":"#/components/schemas/SecurityIssueTypeName"},"rule_id":{"type":"string","title":"Rule Id","description":"Rule identifier shared by every issue in the group. Same value as `rule_id` on the contained issues."},"documentation_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Documentation Url","description":"Public catalog URL for the rule (matches `documentation_url` on each issue). See ``SecurityIssueResponse.documentation_url`` for which scanners populate this."},"package_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Name","description":"Vulnerable package for `DEPENDENCY` / `LICENSE` groups; `null` for SAST / IAC / SECRET."},"package_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Type","description":"Ecosystem of the package (e.g. `npm`, `pypi`, `go`); group-invariant for DEPENDENCY/LICENSE."},"package_licenses":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Package Licenses","description":"Licenses detected for the package (LICENSE groups)."},"severity":{"$ref":"#/components/schemas/SecuritySeverityName","description":"Highest effective severity across the group's active issues."},"issue_counts":{"$ref":"#/components/schemas/IssueCounts"},"first_seen_at":{"type":"string","format":"date-time","title":"First Seen At","examples":["2026-04-28T12:34:56Z"]},"last_seen_at":{"type":"string","format":"date-time","title":"Last Seen At","examples":["2026-04-28T12:34:56Z"]},"tracker_task":{"anyOf":[{"$ref":"#/components/schemas/IssueTrackerTaskSummary"},{"type":"null"}]},"issues":{"items":{"$ref":"#/components/schemas/SecurityIssueResponse"},"type":"array","title":"Issues"}},"additionalProperties":false,"type":"object","required":["id","title","repository_id","repository_name","issue_type","rule_id","documentation_url","package_name","package_type","package_licenses","severity","issue_counts","first_seen_at","last_seen_at","tracker_task","issues"],"title":"SecurityIssueGroupDetailResponse","description":"Group with the full ``SecurityIssueResponse`` for each member issue.\n\nLets a coding agent walk a group's issues without re-fetching each one."},"SecurityIssueGroupResponse":{"properties":{"id":{"type":"integer","title":"Id"},"title":{"type":"string","title":"Title","description":"Best human-readable title for the group. The scanner's group title where available; falls back to the package name (`DEPENDENCY`/`LICENSE`) or the first issue's title."},"repository_id":{"type":"integer","title":"Repository Id"},"repository_name":{"type":"string","title":"Repository Name"},"issue_type":{"$ref":"#/components/schemas/SecurityIssueTypeName"},"rule_id":{"type":"string","title":"Rule Id","description":"Rule identifier shared by every issue in the group. Same value as `rule_id` on the contained issues."},"documentation_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Documentation Url","description":"Public catalog URL for the rule (matches `documentation_url` on each issue). See ``SecurityIssueResponse.documentation_url`` for which scanners populate this."},"package_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Name","description":"Vulnerable package for `DEPENDENCY` / `LICENSE` groups; `null` for SAST / IAC / SECRET."},"package_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Type","description":"Ecosystem of the package (e.g. `npm`, `pypi`, `go`); group-invariant for DEPENDENCY/LICENSE."},"package_licenses":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Package Licenses","description":"Licenses detected for the package (LICENSE groups)."},"severity":{"$ref":"#/components/schemas/SecuritySeverityName","description":"Highest effective severity across the group's active issues."},"issue_counts":{"$ref":"#/components/schemas/IssueCounts"},"first_seen_at":{"type":"string","format":"date-time","title":"First Seen At","examples":["2026-04-28T12:34:56Z"]},"last_seen_at":{"type":"string","format":"date-time","title":"Last Seen At","examples":["2026-04-28T12:34:56Z"]},"tracker_task":{"anyOf":[{"$ref":"#/components/schemas/IssueTrackerTaskSummary"},{"type":"null"}]}},"additionalProperties":false,"type":"object","required":["id","title","repository_id","repository_name","issue_type","rule_id","documentation_url","package_name","package_type","package_licenses","severity","issue_counts","first_seen_at","last_seen_at","tracker_task"],"title":"SecurityIssueGroupResponse","description":"A collection of related security issues — same rule, same package, etc."},"SecurityIssueResponse":{"properties":{"id":{"type":"integer","title":"Id"},"issue_group_id":{"type":"integer","title":"Issue Group Id","description":"The group this issue belongs to (same rule, same package, etc.)."},"repository_id":{"type":"integer","title":"Repository Id"},"repository_name":{"type":"string","title":"Repository Name"},"issue_type":{"$ref":"#/components/schemas/SecurityIssueTypeName"},"rule_id":{"type":"string","title":"Rule Id","description":"Identifier of the rule or finding from the upstream scanner. For `DEPENDENCY` findings this is the CVE or GHSA id; for `SAST` / `IAC` / `SECRET` it's the scanner-emitted rule id. Stability is bounded by the upstream scanner — we pass through what the scanner produces."},"documentation_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Documentation Url","description":"Public catalog URL for the rule. Populated for `DEPENDENCY` findings (NVD / GitHub Advisories); `null` otherwise — OpenGrep / Checkov / BetterLeaks don't have a stable per-rule URL convention. NVD URLs may return `403` for non-browser user agents; prefer the GHSA URL when both ids are available."},"title":{"type":"string","title":"Title"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Path","description":"Path the scanner flagged. For DEPENDENCY findings this is the lockfile — see `manifest_file_path` for the manifest a fix should edit."},"line_start":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Line Start"},"line_end":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Line End"},"commit_sha":{"type":"string","title":"Commit Sha","description":"Git commit at which the issue was last seen."},"source_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Code","description":"Source snippet flagged by the scanner. The first line of the snippet is `source_code_line_start` (1-based, in the file)."},"source_code_line_start":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Source Code Line Start","description":"1-based line number of the snippet's first line in the file."},"package_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Name","description":"Vulnerable package (DEPENDENCY findings)."},"package_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Version"},"package_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Package Type","description":"Ecosystem of the package (e.g. `npm`, `pypi`, `go`)."},"package_licenses":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Package Licenses","description":"Licenses detected for the package (LICENSE findings)."},"fixed_versions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Fixed Versions","description":"Versions that resolve the vulnerability — typically one per release track (e.g. `[\"5.3.5\", \"4.5.4\"]` for backports). Pick the version on the same major/minor track as `package_version`."},"manifest_file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manifest File Path","description":"Manifest a fix should edit (e.g. `package.json` for a `package-lock.json` finding). `null` when no convention applies."},"dependency_graph":{"anyOf":[{"$ref":"#/components/schemas/DependencyGraphResponse"},{"type":"null"}]},"status":{"$ref":"#/components/schemas/SecurityStatus"},"severity":{"$ref":"#/components/schemas/SecuritySeverityName","description":"Effective severity — `severity_override` if set, otherwise the scanner's reported severity."},"original_severity":{"$ref":"#/components/schemas/SecuritySeverityName","description":"The scanner's reported severity, ignoring any override."},"severity_override":{"anyOf":[{"$ref":"#/components/schemas/SecuritySeverityName"},{"type":"null"}]},"snoozed_until":{"anyOf":[{"type":"string","format":"date-time","examples":["2026-04-28T12:34:56Z"]},{"type":"null"}],"title":"Snoozed Until"},"first_seen_at":{"type":"string","format":"date-time","title":"First Seen At","examples":["2026-04-28T12:34:56Z"]},"last_seen_at":{"type":"string","format":"date-time","title":"Last Seen At","examples":["2026-04-28T12:34:56Z"]}},"additionalProperties":false,"type":"object","required":["id","issue_group_id","repository_id","repository_name","issue_type","rule_id","documentation_url","title","description","file_path","line_start","line_end","commit_sha","source_code","source_code_line_start","package_name","package_version","package_type","package_licenses","fixed_versions","manifest_file_path","dependency_graph","status","severity","original_severity","severity_override","snoozed_until","first_seen_at","last_seen_at"],"title":"SecurityIssueResponse","description":"A single finding produced by a security scan."},"SecurityIssueTypeName":{"type":"string","enum":["SAST","IAC","SECRET","DEPENDENCY","LICENSE"],"title":"SecurityIssueTypeName","description":"Category of finding the scanner produced."},"SecuritySeverityName":{"type":"string","enum":["NO_RISK","LOW","MEDIUM","HIGH","CRITICAL"],"title":"SecuritySeverityName"},"SecurityStats":{"properties":{"total_count":{"type":"integer","title":"Total Count","description":"All issues regardless of status (active + snoozed + ignored + solved)."},"active_count":{"type":"integer","title":"Active Count","description":"Issues currently surfaced for triage."},"snoozed_count":{"type":"integer","title":"Snoozed Count"},"ignored_count":{"type":"integer","title":"Ignored Count"},"solved_count":{"type":"integer","title":"Solved Count"},"snoozed_recently_count":{"type":"integer","title":"Snoozed Recently Count","description":"Subset of the corresponding count whose status changed within the last 7 days."},"ignored_recently_count":{"type":"integer","title":"Ignored Recently Count","description":"Subset of the corresponding count whose status changed within the last 7 days."},"solved_recently_count":{"type":"integer","title":"Solved Recently Count","description":"Subset of the corresponding count whose status changed within the last 7 days."},"critical_count":{"type":"integer","title":"Critical Count","description":"Active issues at CRITICAL severity."},"high_count":{"type":"integer","title":"High Count","description":"Active issues at HIGH severity."},"medium_count":{"type":"integer","title":"Medium Count","description":"Active issues at MEDIUM severity."},"low_count":{"type":"integer","title":"Low Count","description":"Active issues at LOW or NO_RISK severity (post-override)."}},"additionalProperties":false,"type":"object","required":["total_count","active_count","snoozed_count","ignored_count","solved_count","snoozed_recently_count","ignored_recently_count","solved_recently_count","critical_count","high_count","medium_count","low_count"],"title":"SecurityStats","description":"Aggregate counts of security issues by status and severity.\n\n`total_count` equals `active_count + snoozed_count + ignored_count +\nsolved_count`. The severity counts (`critical_count` … `low_count`) are\nscoped to **active** issues only and sum to `active_count`."},"SecurityStatus":{"type":"string","enum":["ACTIVE","IGNORED","SNOOZED","SOLVED"],"title":"SecurityStatus","description":"Status of a security issue."},"SecurityStatusInput":{"type":"string","enum":["ACTIVE","IGNORED","SNOOZED"],"title":"SecurityStatusInput","description":"Status a customer can transition an issue to via PATCH.\n\n`SOLVED` is deliberately excluded — issues become `SOLVED` automatically\nwhen the next scan no longer detects them. Setting it manually is a no-op."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}