> ## Documentation Index
> Fetch the complete documentation index at: https://zeropath.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# API Tokens

> Create and manage API tokens for programmatic access to ZeroPath

## Overview

API tokens allow you to access the ZeroPath API programmatically — from CI/CD pipelines, the CLI, the VS Code extension, the MCP server, or custom integrations.

## Creating Tokens

1. Navigate to **Settings → API keys** in the ZeroPath dashboard ([zeropath.com/app/settings/api](https://zeropath.com/app/settings/api)).
2. Click **Create API Key**.
3. Enter a **Token Name** (required). If you are an organization admin, also choose the **Key type**: **Personal key** or **Service key** (see [Token Scopes](#token-scopes)).
4. Set an **expiration** (1–365 days, default: 30 days).
5. Click **Create Token**.
6. **Copy the Token Secret immediately** — it is shown only once and cannot be retrieved later.

You'll receive two values:

* **Token ID** — a UUID identifying the token (safe to log).
* **Token Secret** — the secret key (treat like a password).

## Authentication Headers

Every API request must include both headers:

```bash theme={null}
X-ZeroPath-API-Token-Id: <your-token-id>
X-ZeroPath-API-Token-Secret: <your-token-secret>
```

### Optional: Client identification header

You can optionally send an `X-ZeroPath-Client` header to identify which surface
your integration is calling from. When present, this value is recorded in the
[audit log](/docs/platform/audit-log) so API-token actions are attributed to a specific tool rather than a
generic token call:

| Value | Surface |
| - | - |
| `cli` | ZeroPath CLI |
| `mcp` | MCP server / AI assistant |
| `ide` | IDE extension |

```bash theme={null}
X-ZeroPath-Client: cli
```

Unknown or absent values fall back to a generic API token attribution. The CLI
sends this header automatically — no configuration is needed.

### Example

```bash theme={null}
curl -X POST https://zeropath.com/api/v2/vulnerabilities/search \
  -H "Content-Type: application/json" \
  -H "X-ZeroPath-API-Token-Id: your-token-id" \
  -H "X-ZeroPath-API-Token-Secret: your-token-secret" \
  -d '{"query": "SQL injection in API endpoints"}'
```

## Supported API Surfaces

API tokens authenticate requests to both the V1 and V2 ZeroPath APIs. The V2 API provides expanded coverage including:

* **Vulnerabilities** — list, search, and manage security findings, including remediation and patch metadata when available. Issue details include a `tickets` array listing every linked issue tracker ticket — each entry contains the `provider` (`jira` or `linear`), the ticket `key`, and the ticket `url` (or `null` when a URL is not available). The bulk issue export also includes this `tickets` array on each exported finding, so you can reconcile an export against the Jira or Linear tickets that ZeroPath filed for those findings. Issue list and search results carry the same `tickets` array on every item, built the same way as the export's, so you can see which findings are already ticketed without fetching each one; a ticket's status in Jira or Linear is not included. When a Jira issue is linked to a finding, the API response also includes the Jira issue title alongside the existing issue ID and URL. You can filter the issue list by runtime validation verdict to narrow results to issues with specific validation outcomes. When an issue has been manually marked as non-exploitable, the response includes a `nonExploitableReason` field containing the human triage rationale (distinct from the system-generated `validationSecurityAssessment`). The issue detail response also includes an `exploitationSetup` field — a plain-language description of the configuration or modification a running application would need before the finding can be exploited (empty string when the validator did not characterize it). Patch status metadata now includes the current generation `stage`, so you can track patch progress in real time. Patch details now include a `prSubmission` field (or `null` when no PR submission has been requested) — a discriminated union on `state` that tells you exactly where the submission stands: `QUEUED` (waiting to be picked up), `IN_PROGRESS` (actively being submitted, with a `stage` field such as `PUSHING_BRANCH` or `OPENING_PULL_REQUEST`), `RETRY_SCHEDULED` (failed attempt, with `nextAttemptAt` and `lastError`), `SUCCEEDED` (PR open, with `prLink`), `FAILED` (terminal failure, with a `failureReason` enum such as `RETRIES_EXHAUSTED` or `REPOSITORY_ARCHIVED`, and `lastError`), or `CANCELLED`. You can retrieve all human triage rationales recorded against a repository's findings — including false positives, non-exploitable verdicts, true positives, and severity changes — with a per-entry `disposition` field indicating the triage action. You can update free-form user notes on individual issues (org-shared, up to 5,000 characters; passing an empty or whitespace-only value clears the note). You can also regenerate patches for issues — and if an issue has been marked unpatchable, you can pass `force=true` to override that flag and request a fresh patch attempt. When regenerating, you can supply optional `feedback` (up to 4,000 characters of free-form guidance forwarded to the patch agent) and a `variantCount` (1–3) to generate multiple alternative patch candidates instead of applying one directly; the issue detail response includes a `patchCandidates` array listing each pending alternative (with its diff, PR title, PR description, and blast-radius report) so you can review them before choosing; use `issues.selectPatchCandidate` to promote your preferred candidate into the issue patch and discard the rest. Once a patch is approved, you can cancel the pending pull request submission via `issues.cancelPrSubmission` — cancellation fails with a `CONFLICT` error if the PR is already being created; once the PR exists, use `issues.retryPrSubmission` to re-queue submission after a failure (retry is treated as a fresh user-initiated approval and is rejected if a pull request already exists for the patch). You can update the severity *rating* of an issue by label (e.g., downgrade a "High" to "Medium") — the platform adjusts the underlying severity score to land in the requested band, recording the confidence it scored with. Prefer `updateSeverityRating` whenever you want the displayed rating to change: `updateSeverity` sets only the raw 0–10 severity number, which cannot lift a finding with no recorded confidence out of the Informational band. The `severity`, `confidence`, and `score` fields on issue objects can be `null` — a `null` severity or confidence means the scanner did not record that measurement, and a `null` score means no composite ZeroPath score could be computed. Cross-repository evidence is included in issue details when the scanner identifies related code across multiple repositories, giving you full visibility into multi-repo vulnerability chains. You can exclude specific repository branches from issue list results using `excludedRepositoryBranches` filters. The issue list supports additional filters: `vulnerabilityClassFilters` (structured class matching with `operator` values `equals`, `contains`, or `startsWith`), `hasWizExposure` (limit to findings on Wiz-exposed workloads), `secretVerified` (limit to findings whose detected secret was verified live), `validationStates`, `runtimeValidationVerdicts`, `reachability`, CVSS 4.0 metric filters (`cvssAttackVectors`, `cvssAttackComplexities`, `cvssPrivilegesRequired`, `cvssUserInteractions`), `runtimeValidationSetupRequirements`, `excludeScore` (exclude a specific score value), `issueIds` (fetch a specific set of findings by ID), `createdInLastNDays` and `resolvedInLastNDays` (relative date windows as alternatives to the absolute `createdAfter`/`createdBefore` and `resolvedAfter`/`resolvedBefore` filters). Score range filters now accept `minExclusive` and `maxExclusive` boolean flags to make the bounds exclusive rather than inclusive. The issue list input now uses strict validation — unknown or unrecognized properties in the request body are rejected with an error rather than silently ignored, so you should remove any unsupported filter fields from your requests. When the issue list is requested with no explicit `detectionTypes` filter, the default now covers every category except `CONTAINER` — SCA (dependency) findings are included alongside the code-finding categories, whether or not a free-text `searchQuery` is set — so the API's default population matches the Issues page "All" tab and the dashboard's open-issue total. Previously the default was code-only (SCA was included only during a free-text search); to keep the old behavior, pass `detectionTypes` explicitly without `SCA`. Container findings remain opt-in via `detectionTypes: ["CONTAINER"]`. Issue details now include Wiz runtime evidence when a Wiz integration is connected, providing workload context such as running status, sensitive data exposure, internet reachability, and attribution details for the repository's deployed workloads — both at the time of detection and the latest lookup. The issue detail response now includes a `securityCompassCountermeasures` array listing every SD Elements countermeasure linked to the issue — each entry includes the mapping id, project id, task id, title, a link back to the SD Elements task, the match method (`NL_RULE_FK` for deterministic rule-based links or `LLM` for model-matched links), whether it is the primary countermeasure reported against in SD Elements, and the model rationale for LLM matches
* **SCA** — list dependency vulnerabilities with severity, reachability data, and patch status metadata when a remediation exists. The vulnerability search endpoint uses cursor-based pagination with `hasMore` and `nextCursor` fields; to retrieve the total count of matching findings, use the dedicated count endpoint (`/api/v1/sca/vulnerabilities/count`) which accepts the same filter parameters — including `scanId` to count findings from a specific scan, `status` to filter by lifecycle state (all, open, or closed), `severities` and `packageReachability` to narrow by severity bucket or reachability verdict, `isCompiled` to distinguish compiled assets from manifest-declared dependencies, `hasFix` to count only findings with a recommended fix version, and `includeEphemeral` to include ephemeral repositories. You can filter SCA alerts and vulnerabilities to only those associated with applications exposed by Wiz. SCA advisories now include exploit intelligence fields — CISA KEV status (`isKnownExploited`, `kevDateAdded`, `kevKnownRansomware`) and FIRST EPSS scores (`epssScore`, `epssPercentile`) — so you can prioritize based on real-world exploitation data. You can list dependency-resolution coverage warnings to identify manifests where the dependency tree could not be fully resolved, and query per-ecosystem resolution coverage to quantify how complete your dependency scanning is across repositories. When listing SCA facet options, you can pass a `facets` parameter to selectively compute only the option lists you need (`dependencies`, `advisories`, or `ecosystems`) — asking for fewer facets is faster, and omitting the parameter computes all of them. All SCA list endpoints (vulnerabilities, licenses, packages, posture, and repository inventory) accept an optional `branch` parameter — when supplied, each repository's data is read as of its newest finished scan on that branch rather than the newest scan on any branch. SCA scan objects and manifest list responses include an `inventoryRetiredAt` timestamp (or `null` while still current) that tells you when a scan's dependency inventory was superseded by a newer scan on the same branch; a non-null value means the inventory data is historical. The repository inventory response additionally exposes `branch`, `commitSha`, and `codeScanId` on each item so you can correlate a dependency snapshot back to the exact commit and code scan it was produced from. Package detail responses include a `dependencyPathsRetiredAt` timestamp when the dependency-path data originates from a retired inventory
* **Reports** — generate security reports in DOCX, CSV, SARIF, or SBOM format. If report generation fails, the report status is updated to `failed` with an error message describing what went wrong. All report types (organization summary, SLA compliance, SOC 2, and compliance reports) now accept a `scope` parameter to target a specific subset of repositories — pass `repositoryIds` to select individual repositories, `tagIds` to select repositories by tag, or omit both for the full organization. Before generating a report, you can call `previewScopeRepositoryCount` with the same scope parameters to preview how many repositories the report will cover without triggering generation. The SBOM export endpoint now returns `404` when the requested scan cannot be found (or its associated dependency scan no longer exists), and `412 Precondition Failed` when the scan's dependency inventory has been retired because a newer scan on the same branch superseded it — in the `412` case, re-run the export against the latest scan for that branch rather than retrying the same scan ID. Compliance reports now include an **Unassessed** severity band in both the summary table and per-repository breakdown — this band captures findings for which no severity was ever measured (for example, a dependency advisory with no CVSS score); they are counted in the total vulnerability figure but belong to none of the five scored bands (Critical, High, Medium, Low, Info). Score-threshold filtering in report generation now correctly excludes unassessed findings: only findings with a measured score are compared against the threshold, so a null-score finding is never treated as having a score of 0
* **Custom Reports** — create, list, and delete saved filter configurations, retrieve aggregated statistics (severity distribution, top vulnerability classes, MTTR, trends), and discover available filter fields via the filter schema endpoint. The filter schema now includes additional filterable fields: `runtimeValidationVerdict`, `cvssAttackVector`, `cvssAttackComplexity`, `cvssPrivilegesRequired`, `cvssUserInteraction`, and `runtimeValidationSetupRequirement`. New filter operators are also available: `isUnknown` (matches findings whose value for a field is unknown/unset), `onOrAfter`, and `onOrBefore` (inclusive date comparisons, as complements to the existing `after` and `before` operators)
* **Threat Models** — retrieve and edit threat models for your applications. Each threat model section includes `customerEdited` (boolean indicating whether a customer has saved edits), `customerEditedAt` (ISO timestamp of the last customer edit, `null` until edited), and `updatedByUserName` (display name of the last editor, `null` until edited). While `customerEdited` is true, scan-time regeneration never replaces the section content. The threat model object includes `agentGeneratedAt` (ISO timestamp when the scanner agent last wrote section bodies, `null` for models that predate regeneration) and `evidenceCheckedAt` (ISO timestamp of the last comparison between the application's current inventory and the fingerprint the sections were written from, `null` when no comparison has been made). Application overview objects include `llmContextEdited` (boolean indicating whether a customer has saved the overview; while true, application re-identification never overwrites the overview)
* **AI Inventory** — list repositories and component providers detected by the AI inventory scanner. Both list endpoints accept an optional `branch` parameter to scope results to each repository's newest finished scan on that branch, rather than the newest scan on any branch.
* **Endpoints** — semantic search across detected endpoints and data handlers
* **Agent**: manage event triggers, patches, pull requests, global agent instructions, trigger history, real-time job streaming via SSE, and playbooks (activate, pause, and uninstall pre-built security automation workflows from a template library). Playbook templates support rich parameter types including text, number, boolean toggles, and select dropdowns, giving you fine-grained control when activating workflows. Read-only operations (listing event triggers, playbook instances, trigger history, retrieving a specific trigger event, and reading global instructions) require only the **View Agent** permission; you do not need **Run Agent** to query these resources. You can also check whether the AppSec Assistant is enabled for your organization (`agent.getAvailability`) using only the **Run Agent** permission. This lets your integration confirm availability before composing a message, receiving a clear disabled state instead of a failed conversation creation. Agent conversations and jobs are scoped by repository-level access control: if a conversation is bound to a repository, only users who hold view access on that repository can list, read, send messages to, or archive the conversation. Losing repository access automatically hides those conversations and jobs from all agent endpoints. Recurring (cron-triggered) agent jobs are automatically linked to an entry under **Assistant → Configure → Schedules** (shown to organization admins). If a run arrives without an existing schedule record, one is created so every recurring task is visible and can be paused from the dashboard; a run for a schedule you have already paused is silently skipped rather than executed. When creating a conversation or sending a message, you can pass `planFirst: true` to request that the agent propose a step-by-step plan before executing anything. The agent pauses after producing the plan so you can review, edit, add steps, or reject it before any work runs. Plans are managed through the **Agent Plans** endpoints (`agentPlans.listPlans`, `agentPlans.approvePlan`, `agentPlans.rejectPlan`): listing returns all plans for a conversation in chronological order with their steps, scope, risks, and expiry state; approving submits the (optionally edited) step list and starts an execution job; rejecting discards the proposal. A plan expires if not acted on within its window, and an expired plan must be rejected and a new one requested. You can manage the agent's built-in and custom skills via `agent.listSkills`, `agent.setSkillEnabled`, `agent.duplicateSkill`, `agent.upsertSkill`, and `agent.deleteSkill`. Built-in skills can be enabled or disabled per organization; forking a built-in with `duplicateSkill` creates an editable copy scoped to your organization and automatically opts out of the original so only your copy is active. Disabling a built-in requires **Manage Agent**, which only organization admins hold (it cannot be granted to a team); reading the skill list requires only **View Agent**. The real-time SSE job stream delivers only user-visible messages: internal agent housekeeping messages are filtered out, so every event your client receives is directly relevant to the conversation. When an agent job fails, the stream delivers a human-readable failure message (with role `ERROR`) before the terminal `final` event, so your client can display what went wrong without needing a separate API call. If the SSE connection itself is interrupted by a server error, the stream sends a safe reconnection prompt instead of exposing internal details. Recurring (cron-triggered) agent jobs that fail automatically send a failure notification to the configured Slack channel, so schedule owners are alerted without polling for job status. When the agent approves a pull request for a patch, requesting a PR submission leaves the finding's validation verdict unchanged. The two concerns (submitting a PR and confirming exploitability) are tracked independently, so your manually set or assessor-confirmed validation status is always preserved. If the platform refuses a PR submission (for example, because the patch does not meet a required precondition), the agent endpoint returns a `409 Conflict` response containing the specific failure reason, the same reason shown on the issue page
* **On-Demand Code Scans Beta** — submit diffs, files, and snippets for asynchronous security review from CLIs, IDEs, pre-commit hooks, and custom integrations
* **Rule Packs** — browse curated bundles of natural-language SAST rule templates covering compliance, privacy, logging, and more; enable or disable individual templates or entire packs for your organization. Rule pack activation requires a user account — agent sessions receive a permission error
* **Custom Rules** — create, update, and list natural-language security rules. Rules can be scoped to all repositories (default), specific repositories, or by tag — pass `tagIds` without `repositoryIds` to scope a rule to repositories carrying those tags. Each rule's response includes a `scope` field (`allRepositories`, `repositories`, or `tags`) so you can see how it is applied. List and get responses also include a `source` field (`USER` or `SECURITY_COMPASS`) indicating whether the rule was created manually or auto-generated from an SD Elements countermeasure. When a rule was created from a rule pack template, the response includes a `template` field with the template name and the pack it belongs to, so you can trace the rule back to its origin
* **Organizations** — manage organizations, list/invite/remove members, and update member roles. When inviting a new member, you can optionally specify a role (`ADMIN` or `MEMBER`); the default is `MEMBER`, and inviting as `ADMIN` requires admin-level permission. The member list returns a clear status for each member — `active`, `pendingInvite`, or `scimDeprovisioned` — so you can distinguish active members from outstanding invitees and identity-provider-deprovisioned users. Removing a member works for active members and for pending or expired invitees (their outstanding invitation is automatically revoked); active admins cannot be removed directly — demote them to a regular member first. SCIM-deprovisioned members must be managed through your identity provider instead. Re-inviting an email address that already has a pending or expired invitation automatically revokes the old invitation and sends a fresh one. GitHub team sync status includes a `lastTeamSyncAt` timestamp showing when the most recent sync completed, and you can trigger an immediate on-demand sync via the API or the dashboard. You can enable or disable GitHub direct collaborator sync for your organization, which syncs individual repository collaborator permissions alongside team-based access. When a sync encounters an error, the sync status response includes a `syncError` field with the error message, so you can diagnose issues without contacting support. Direct collaborator sync is not supported for GitHub Enterprise Server installations. The GitHub team sync status response now includes an `orgBaseRepoPermissions` array — one entry per connected GitHub organization — reporting each installation's base repository permission and a `grantsBaseReadToAllMembers` flag; when any installation grants blanket read to all members, `anyInstallationGrantsBaseRead` is also `true` in the response. Bitbucket group sync is now available: you can enable or disable it (`updateBitbucketTeamSync`), trigger an immediate sync (`syncBitbucketTeamsNow`), and read its current status and unmatched contributors (`getBitbucketTeamSyncStatus`) — all under the same admin-only access requirement as the GitHub counterparts. The unmatched-contributors list now includes contributors from all team-sync-capable platforms (GitHub and Bitbucket), with a `platform` field on each entry so you can tell which host the account came from
* **Repositories** — list, add by URL (public repos), delete, and manage repository settings. Repository responses include VCS-specific configuration for GitHub, GitLab, Bitbucket, Azure DevOps, Gerrit, CVS, generic Git, and uploaded (standalone) repositories, so you can identify the source provider and connection status for each repository. When updating repository scanner settings, the `maxPrTimeoutMinutes` field must be an integer between 5 and 1440 (5 minutes to 24 hours) — values outside this range or non-integer values are rejected with a validation error. Gerrit repositories carry a `state` field (`ACTIVE`, `READ_ONLY`, or `HIDDEN`) indicating project availability on the Gerrit server — `READ_ONLY` projects are still scannable but patches cannot be proposed against them. CVS repositories are addressed by a `(cvsRoot, modulePath)` pair and expose a `transport` field (`CVS_CHECKOUT` or `SCP_DIRECTORY`) describing how the module is retrieved; their `url` is a `cvs+pserver:` or `scp:` URI rather than a browsable web address, and `branchTag` is `null` for trunk. You can resolve a repository by URL and the response now includes `gerrit` and `cvs` as valid `vcs` values. The branch-listing endpoint supports Gerrit and CVS in addition to the existing providers; CVS exposes its single materialized branch. For monorepo setups, you can atomically delete all partitions of a monorepo in a single operation, and previously deleted repositories can be re-imported without issues. Tags can be marked as **default** (`isDefault: true`) so they are automatically applied to every newly added repository, ensuring consistent tagging and team access from the moment a repository is imported. Repository objects returned by the repository list endpoint carry a `lastScanFailure` field, so you can see why a scan did not complete without inspecting individual scan records. It reports on the newest *finished full* scan only — pull-request scans and scans still in flight never set it. It is `null` when that scan succeeded, when the repository has no finished full scan yet, or when no user-facing message could be derived; otherwise it is an object with `message` (the error text), `outcome` (`FAILED` or `CANNOT_SCAN`), and `details` — a structured object containing the `scanId`, the `branch` the scan was targeting (or `null`), and a `recovery` hint (`CONNECTION` when retrying may succeed after fixing connectivity, `BRANCH` when the failure is branch-related, or `NONE` when no automated recovery path is known). Note that a successful scan newer than a failed one leaves the field `null`. The legacy `lastScanError` field (string or null) is emitted alongside `lastScanFailure` as a deprecated alias of `lastScanFailure.message`; migrate to `lastScanFailure`. The `defaultBranch` field is now `string | null` — it returns `null` for repositories that the VCS reports as having no default branch (for example, a newly created empty repository). When resetting repository scanner settings, the response returns a `resetCount` field indicating the number of repository scopes whose overrides were cleared
* **Container Scanning** — submit container images for vulnerability scanning by registry reference or by uploading an image archive (for air-gapped environments). You can list and retrieve tracked container images, view scan results with per-layer attribution and base-image upgrade recommendations, list vulnerability findings grouped by package with aggregated CVEs, and manage recurring monitoring schedules via cron expressions. The container dashboard summary provides organization-wide statistics including image counts, findings by severity, and top base-image upgrade opportunities. You can link images to repositories, delete tracked images, and check whether container scanning is enabled for your organization. Container image objects include a `registryConnection` field (containing `id` and `displayName`, or `null`) that identifies an org-level registry connection supplying pull credentials — a reusable alternative to inline per-image credentials. When submitting an image, you can pass `registryConnectionId` to link an existing org-level connection instead of providing inline `registryUsername`/`registryToken`; these two approaches are mutually exclusive. Passing `clearRegistryAuth` clears both inline credentials and any linked registry connection, reverting the image to an anonymous pull. The `monitoringCrontab` field on the submit request accepts three states: a string sets the schedule, an explicit `null` clears an existing schedule, and omitting the field leaves any existing schedule unchanged. Submitting a registry image reference that matches the name of an existing uploaded-archive image in the same repository returns a `409 Conflict` — use a different name or attach the image to a different repository to resolve the conflict
* **Scans** — trigger full scans, cancel running scans, and manage cron-based scan schedules with branch targeting. Scan responses include repository identifiers for all supported VCS providers (GitHub, GitLab, Bitbucket, Azure DevOps, Gerrit, Generic Git, and CVS) via the corresponding `gerritRepositoryId`, `genericGitRepositoryId`, and `cvsRepositoryId` fields — these fields are now included in every scan list item and scan detail, making it straightforward to correlate scans back to your Gerrit and CVS repositories. You can scan all VCS-attached repositories at once by passing `allRepositories: true`, optionally excluding specific repositories with `excludedRepositoryIds`. You can filter the scan list by severity level (Critical, High, Medium, Low) and group PR scans by pull request to see only the latest scan per PR along with a count of related rescans. Scan list results respect per-repository access control — you only see scans for repositories you have view access to, consistent with how access control works across all other platform surfaces. If a full scan is already in progress for the same repository and branch, the API returns an error rather than starting a duplicate scan. When rescanning a PR, the `force` flag now runs a full scan instead of an incremental refresh. When starting a multi-repository scan, repositories that cannot be scanned (for example, due to missing branch configuration or billing issues) are automatically skipped rather than blocking the entire batch — the remaining eligible repositories proceed normally. For credit-billed scans, if the repository's usage estimate is still being computed at quote time, the scan proceeds immediately and is billed at the pricing policy's minimum charge — the `estimatedBillableTokens` field in the quote response will be `null` in this case rather than a token count
* **Runtime Validation** — dynamically test confirmed findings inside isolated containers. You can auto-provision a source-build validation profile for a single application (`runtimeValidation.autoProvisionAndValidate`) or for every detected application in a repository at once (`runtimeValidation.autoProvisionAndValidateRepository`) — no manual profile configuration or uploaded artifact required, just supply a completed scan id. Applications already queued are skipped automatically. Runtime validation profiles now support a `SOURCE_BUILD` target mode in addition to `REMOTE_CONNECTIVITY` and `LOCAL_ARTIFACT`; source-build profiles are built and run directly from the repository source inside the validation environment. Each finding carries a `setupRequirement` field (`DEFAULT_SETUP`, `REQUIRES_MODIFICATION`, or `UNKNOWN`) indicating whether it is reachable under the default provisioned environment. After a run completes you can call `runtimeValidation.listExploitChains` to retrieve multi-step exploit chains — sequences of confirmed findings that, when chained together, reach higher combined impact than any individual finding — ordered by combined severity and including per-step roles, configuration requirements, proof-of-concept instructions, and a setup requirement for the chain as a whole
* **Teams**: create teams, manage memberships, configure granular organization/repository/team permissions, and manage default permission templates that can be applied to all teams or specific teams in your organization. Repository access can be granted globally (all repos), per-repository, or by tag. Tag-based grants automatically cover every repository that belongs to the tag, so access stays in sync as repositories are added or removed. When GitHub direct collaborator sync is enabled for your organization, each user's effective repository access is the union of their team-based grants and their individual GitHub collaborator permissions, so a user who is a direct collaborator on a GitHub repository can access it in ZeroPath even if none of their teams grant access to that repository. Contributors discovered through direct collaborator sync are surfaced in the unmatched contributors list with a `DIRECT_REPOSITORY` provenance indicator, distinct from team-sourced contributors, so you can see how each contributor's access was derived. Updating or deleting a tag that has team permission grants requires the **Manage Teams** permission, and repository IDs supplied when creating or updating a tag are validated to belong to your organization. When reading a team's permissions, the response includes a structured `repoAccess` field that explicitly indicates the access mode (`universal` or `selected`) along with the effective permissions, repository IDs, and tag IDs. The **Run Agent** permission implicitly includes **View Agent**: granting a team the ability to run the agent automatically grants view access as well, so you do not need to assign both permissions separately. Two new repository-level permissions are available: `ISSUE_CREATE_JIRA_TICKET` (**Create Jira Tickets** in the team permission editor) controls the ability to create a Jira ticket from a finding, and `ISSUE_CREATE_LINEAR_TICKET` (**Create Linear Tickets**) controls the ability to create a Linear ticket from a finding. Grant these alongside existing issue permissions to allow your team to file tracker tickets directly from ZeroPath. You can customize how GitHub repository roles (Pull, Triage, Push, Maintain, Admin) map to ZeroPath repository permissions during GitHub team sync. Use `teams.getGithubSyncRolePermissions` to view the current mapping and ZeroPath's built-in defaults, and `teams.setGithubSyncRolePermissions` to replace it with a custom mapping or reset to defaults. Custom mappings must specify all five GitHub roles at once so the stored mapping is always complete. Changes take effect on the next sync. Viewing the mapping requires the **View Teams** permission; updating it requires **Manage Teams**. You can also customize how Bitbucket repository roles (Read, Write, Admin) map to ZeroPath repository permissions during Bitbucket team sync. Use `teams.getBitbucketSyncRolePermissions` to view the current mapping and ZeroPath's built-in defaults, and `teams.setBitbucketSyncRolePermissions` to replace it with a custom mapping or reset to defaults. Custom Bitbucket mappings must specify all three roles at once, follow the same sync-managed permission restriction as GitHub mappings, and take effect on the next sync. Viewing the mapping requires **View Teams**; updating it requires **Manage Teams**. The `ORG_EDIT_REMOTE_MCP` organization-level permission (**Enable or Disable Remote MCP**) controls the ability to manage remote MCP server configuration for your organization. The `DASHBOARD_TEMPLATE_MANAGE` organization-level permission (**Manage Dashboard Templates**) controls the ability to create and manage dashboard templates for your organization. When setting team or default-template organization-level permissions, certain admin-only permissions are rejected at input validation. If you receive a validation error about a permission that cannot be granted to a team, remove it from the `organizationPerms` array
* **Custom Sources** — create, list, update, toggle, and delete custom security source declarations that tell the scanner about additional untrusted data entry points in your code
* **Custom Sinks** — create, list, update, toggle, and delete custom security sink declarations that tell the scanner about additional security-sensitive operations in your code
* **Custom Source Packs** — browse curated bundles of source declaration templates, enable or disable individual templates or entire packs
* **Custom Sink Packs** — browse curated bundles of sink declaration templates, enable or disable individual templates or entire packs
* **Integrations** — read data from third-party integrations such as Wiz CSPM, including retrieving Wiz settings, listing Wiz projects, and searching Wiz cloud assets and network exposures. Notification rules now support Microsoft Teams as a delivery channel — set `channels` to include `TEAMS` and supply a `teamsChannelIds` array when creating or updating a rule; selecting Teams without at least one valid channel ID is rejected. Removing Teams from the `channels` array automatically clears the stored channel IDs
* **Security Compass** — manage the SD Elements integration end-to-end via the public REST API (`/api/v2/securityCompass/*`): read the integration and project mappings, test the connection, add and remove project-to-repository mappings, trigger countermeasure-to-rule syncs, retrieve the per-countermeasure coverage audit, fetch linked findings for a countermeasure, and view the Security Compass audit log. Credentials (the SD Elements API token and base URL) are managed only in the ZeroPath dashboard — the API never accepts or returns them. Testing the connection requires the same admin-level permission as managing the integration — the test connection endpoint validates both authentication and the target URL before dialing. Managing the integration requires the admin role; read operations are available to all members. See the [Security Compass integration guide](/docs/integrations/security-compass) for the full workflow
* **Scanner Settings** — configure scan modules, confidence thresholds, auto-patching, and file ignore patterns at org, repo, or app scope. When deleting scanner settings overrides for a scope, organization and repository scopes retain their assigned rules, contexts, custom sources/sinks, and pattern sets while reverting configuration overrides; tag scopes are removed entirely, unassigning any records attached to them. Enabled scan modules now include `CONTAINER` alongside SAST, IAC, SECRETS, EOL, SCA, and AI. The release track for full scans and PR scans accepts `STABLE` in addition to `EDGE`. The `allowPrCheckBypass` setting controls whether contributors can bypass the ZeroPath PR check status without disabling PR scanning entirely. The `fullScanAutoProvisionRuntimeValidation` setting enables automatic source-build runtime validation provisioning after each full scan, so detected applications are validated without any manual profile configuration. The `scanOnFirstMeaningfulCommit` setting (boolean or null to inherit) controls whether ZeroPath automatically triggers a scan when a repository receives its first meaningful commit, useful for repositories that are initially empty at import time. The `scanOnEveryMeaningfulCommit` setting (boolean or null to inherit) controls whether ZeroPath triggers a scan on every meaningful commit push, enabling continuous scanning beyond the first commit
* **Stats** — retrieve aggregate issue counts and scan activity by scope, including a breakdown of issues by application with open and resolved counts per repository. Dashboard statistics endpoints accept optional application filters to narrow results to specific applications within repositories. The security posture summary includes a `reachableExploitableIssues` count alongside the existing severity-level counts. The summary endpoint now correctly honors the `repositoryId` and `scanId` scope filters — previously these parameters were accepted but had no effect on the returned counts; they now narrow the issue population and scan activity to the specified repository or scan. When you pass a `scanId`, scan activity metrics are scoped to that scan and issue counts reflect only the findings from that scan rather than the whole organization. The summary issue counts now include SCA (dependency) and container findings alongside SAST, secrets, IaC, and other detection types, matching the counts shown on the Issues page. Exposure and remediation-time fields (`meanRemediationTime`, `meanCriticalExposure`, `meanHighExposure`, `meanMediumExposure`, `meanLowExposure`, `meanInfoExposure`, `oldestCriticalAge`, `oldestHighAge`, `oldestMediumAge`, `oldestLowAge`, `oldestInfoAge`) can now be `null` when there is insufficient data to compute a meaningful value — treat `null` as "no data" rather than zero. Each trend point now carries `meanRemediationTimeInPeriod` (mean days to resolve over the issues resolved in that period only, `null` when none) and `resolvedIssues` gives its sample size; the summary carries `resolvedIssuesInWindow`, the count behind `summary.meanRemediationTime`. The trend field `meanRemediationTime` is a running average from the start of the requested range and is deprecated: it will be removed in a later release, so read `meanRemediationTimeInPeriod` instead. The trend history endpoint now accepts `quarter` as a `timeGranularity` value in addition to `day`, `week`, and `month`. If the requested posture scope is too large to compute within the query time budget, the endpoint returns a `408` response — retry with fewer repositories, as repeating the same scope will not succeed

For a full list of available endpoints, see the [API Reference](/docs/api-reference/introduction).

## Token Scopes

There are two kinds of token.

A **personal token** is the default, and any member can create one for themselves. No special permission is required, because the token carries your own permissions and nothing more. It acts as you: every permission check and every repository access-control grant applies to it exactly as it does when you use the dashboard. If your team grants you access to three repositories, your token reaches those three repositories.

A personal token is **pinned to the organization it was created in** and cannot act in any other, even if you belong to several. A request naming a different organization is rejected. To work in another organization, create a token there.

A **service token** is an organization-wide machine credential that belongs to no one. It is not held to any individual's permissions, so it keeps working after the person who created it leaves. Only organization admins can create one. Use it for automation that should outlive an individual, and a personal token for everything else.

There is no fine-grained scope selection at token creation time.

<Note>
  Tokens created before September 2026 became personal tokens owned by whoever created them, pinned to the organization they were created in. If an integration previously relied on a token acting with admin authority regardless of its owner, replace it with a service token.

  This is the only change a live integration can observe. If one of your tokens was being used against more than one organization, the requests naming the organization it is not pinned to now fail with `API_TOKEN_ORGANIZATION_MISMATCH`. Create a token in each organization you need to reach.
</Note>

## Managing Tokens

Token creation, listing, and revocation require a signed-in browser session. API tokens, MCP credentials, and OAuth credentials cannot manage tokens, including revoking themselves. Use **Settings → API keys** to rotate or revoke a credential.

From the **API keys** settings page, you can:

* **View** your own keys on the **My keys** tab, with their names, a **Service key · organization-wide** badge on service keys, expiration dates (expired keys are marked **Expired**), and when each was last used.
* **Delete** any of your own tokens at any time.

Members with the **View API Tokens** permission also see an **Organization keys** tab listing every token in the organization and who owns it. Deleting someone else's token, or a service token, requires **Delete API Tokens**.

Tokens cannot be edited after creation. To change a token's expiration or name, delete it and create a new one.

## Token Lifecycle

* Tokens have a fixed expiration date set at creation (1–365 days).
* **Expired tokens are automatically rejected** — there is no automatic renewal.
* When a token expires, create a new one and update your integrations.
* Token secrets are cryptographically hashed before storage — ZeroPath never stores the plaintext secret.

## Troubleshooting

### `INVALID_API_TOKEN` error

If the API responds with an `INVALID_API_TOKEN` error, it means the token ID/secret pair is unknown, expired, or does not match the deployment being called. All three cases return the same error so the response cannot be used to probe whether a token ID exists.

The most common non-obvious cause is a **deployment mismatch**: API tokens are valid only on the ZeroPath deployment that issued them. If your organization uses a dedicated deployment (`https://<name>.zeropath.com`), tokens created there will not work against `https://zeropath.com`, and vice versa. Check that the host in your API calls matches the host where the token was created.

### `API_TOKEN_ORGANIZATION_MISMATCH` error

Personal API tokens are pinned to the organization they were created in. If you send a request that names a different organization, the API returns an `API_TOKEN_ORGANIZATION_MISMATCH` error. This is not a credential problem — the token itself is valid, but it cannot act outside its organization.

To work in another organization, create a token in that organization instead. You do not need to supply an `organizationId` header when using a personal token — the platform automatically scopes the request to the token's pinned organization.

## Best Practices

1. **Use descriptive names** — name tokens after their purpose (e.g., "CI/CD Pipeline", "VS Code Extension", "MCP Server").
2. **Set short expirations** — use the shortest practical expiration for your use case.
3. **Rotate regularly** — create new tokens and retire old ones on a schedule.
4. **Never commit tokens to source control** — use environment variables or a secrets manager.
5. **One token per integration** — avoid sharing a single token across multiple systems so you can revoke individually.
6. **Delete compromised tokens immediately** — if a token may have been exposed, delete it and create a replacement.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.