Download OpenAPI specification:Download
Open-source self-hosted SCA portal — CVE, license compliance, and SBOM management with EPSS prioritization, VEX consumption, CI build gating, and Trivy-backed CVE matching with weekly DB refresh + automatic re-matching on new vulnerability data.
Public — no authentication required, but limited per
PASSWORD_RESET_RATE_LIMIT (5/min/IP by default).
Body shape: {"email": "<address>"}. Always returns 204 + empty body
(CWE-204). When the address matches a registered user we additionally
enqueue an email via Celery. When the per-email cooldown is active we
set Retry-After to the configured cooldown and STILL return 204.
| email required | string <email> (Email) |
{- "email": "user@example.com"
}{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Public — no authentication required, but limited to 5 attempts/minute/IP.
On success: 200 + access_token in the body, refresh as HttpOnly cookie. On bad credentials: 401 problem+json.
| email required | string <email> (Email) |
| password required | string (Password) [ 1 .. 256 ] characters |
{- "email": "user@example.com",
- "password": "string"
}{- "access_token": "string",
- "expires_in": 0,
- "token_type": "bearer"
}Revoke the refresh cookie. Idempotent — always returns 204 even if the cookie is absent or already revoked.
Refresh Token (string) or Refresh Token (null) (Refresh Token) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Authenticated. UserPublic + the caller's team memberships.
The frontend reads memberships to resolve a team_id for project
creation / write scoping. Ordered oldest-first so memberships[0] is a
stable default team.
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false
}Public. The pending token from POST /auth/login is the credential, and it
is worth nothing on its own.
On success: 200 + access_token, refresh as an HttpOnly cookie. This is the first point at which a session exists.
| code required | string (Code) [ 1 .. 64 ] characters |
| mfa_token required | string (Mfa Token) [ 1 .. 4096 ] characters |
{- "code": "string",
- "mfa_token": "string"
}{- "access_token": "string",
- "expires_in": 0,
- "token_type": "bearer"
}Public — no authentication required (explicit exception to CLAUDE.md core rule #12: the consumer is the anonymous /login page, which must decide which OAuth sign-in buttons to render BEFORE any credential exists).
Always lists every supported provider with a bare configured
boolean. configured is True only when both the client id AND
client secret are set — the same condition under which
/{provider}/authorize actually works (M-15: a half-configured or
unconfigured provider previously surfaced as a rendered button that
503'd on click).
Security: the response carries booleans only — never client ids, secrets, or any other configuration detail.
{- "providers": [
- {
- "configured": true,
- "provider": "github"
}
]
}Public — the provider's redirect lands here after consent.
Success path: 302 → redirect_after (or configured default) with the
refresh-token HttpOnly cookie attached.
Failure path: 302 → configured failure URL with ?error=<reason>. The
provider's own ?error=access_denied (user clicked "Cancel") falls
through here too — we forward a normalised error=oauth_denied.
Read-only demo: if DEMO_READ_ONLY is enabled we 403 BEFORE any token
exchange or DB write (see :func:_demo_read_only_blocked), so the callback
can never create/link a User or Team in the demo.
| provider required | string (Provider) Enum: "github" "google" "oidc" |
Code (string) or Code (null) (Code) | |
State (string) or State (null) (State) | |
Error (string) or Error (null) (Error) |
nullPublic — the refresh cookie is the credential.
Successful rotation: 200 + new access_token + new refresh cookie. Reuse detected (cookie already rotated): 401, entire chain revoked.
Refresh Token (string) or Refresh Token (null) (Refresh Token) |
{- "access_token": "string",
- "expires_in": 0,
- "token_type": "bearer"
}Public, no authentication required.
Limited to REGISTRATION_RATE_LIMIT (5/min/IP by default): the bcrypt
password hash is CPU-bound, so an uncapped public endpoint could occupy
the worker's event loop with unauthenticated requests.
Returns the new user (without password). 422 for validation errors, 409 if
the email is already registered, and 404 when the deployment maintains its
roster itself (AUTH_SELF_REGISTRATION=false), which is the same answer
an outsider gets for any route that is not there.
| email required | string <email> (Email) |
Full Name (string) or Full Name (null) (Full Name) | |
| password required | string (Password) [ 8 .. 256 ] characters At least 8 characters (NIST 800-63B minimum), not a common password. |
{- "email": "user@example.com",
- "full_name": "string",
- "password": "stringst"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true
}Public — the reset token is the credential.
Limited to PASSWORD_RESET_CONFIRM_RATE_LIMIT (5/min/IP by default,
same as login): the token is guessable the same way a password is, and
the verify path costs a bcrypt call per live candidate, so this
endpoint needs no less protection than login (F1,
concurrency-scaling-plan-2026-08-22.md).
On success: 204 + every refresh token for the user is revoked. On bad / expired / used token: 422 problem+json.
| new_password required | string (New Password) [ 8 .. 256 ] characters At least 8 characters (NIST 800-63B minimum), not a common password. |
| token required | string (Token) [ 8 .. 256 ] characters |
{- "new_password": "stringst",
- "token": "stringst"
}{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Cheap PURE-LIVENESS probe used by docker-compose / k8s liveness checks.
PUBLIC / unauthenticated (CLAUDE.md rule #12 explicit exception). This proves only that the uvicorn process is accepting requests — it does NOT touch the database and says nothing about schema state. For "is the schema migrated and safe to serve traffic / start workers", use GET /health/ready (api/v1/health.py).
v2.1 Track B (B5): also surfaces demo_read_only so the SPA can render the
read-only banner and disable write actions without needing a separate build.
The flag is resolved at request time (CLAUDE.md rule #11), so the same image
behaves correctly whether DEMO_READ_ONLY is set or not.
Also surfaces demo_sandbox_scans — only true when the read-only demo has
the opt-in sandbox carve-out enabled (both DEMO_READ_ONLY and
DEMO_ALLOW_SANDBOX_SCANS). The SPA uses it to re-enable the bounded
scan / SBOM-ingest affordances on the Demo Sandbox project while keeping
every other write disabled.
{ }Return 200 when the DB schema matches the Alembic HEAD, else 503.
PUBLIC: no auth dependency by design (probe endpoint — see module docstring
and CLAUDE.md core rule #12). The check is read-only (a single SELECT on
alembic_version plus an in-image read of the script tree).
The redis field is observational only (issue #399): it never changes
the status code, so a Redis outage does not pull the backend out of an
orchestrator's rotation for a dependency the request path already fails
open through. See core.readiness for the reasoning.
{- "redis": "ok",
- "status": "ready"
}Return what this deployment is, and which notices it can show.
{- "built_at": "2026-09-06T02:11:00Z",
- "commit": "a0d2bab",
- "copyright": "Copyright 2026 TRUSCA contributors",
- "documents": [ ],
- "license_name": "Apache License, Version 2.0",
- "license_spdx_id": "Apache-2.0",
- "product": "TRUSCA",
- "version": "2.3.0-dev"
}Return one notice document as text/plain.
Verbatim: a license text that has been reflowed, truncated or markdown-rendered is no longer the notice it is standing in for.
| document_id required | string (Document Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Actor User Id (string) or Actor User Id (null) (Actor User Id) | |
Target Table (string) or Target Table (null) (Target Table) | |
Action (string) or Action (null) (Action) | |
From (string) or From (null) (From) | |
To (string) or To (null) (To) | |
Q (string) or Q (null) (Q) | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "has_more": true,
- "items": [
- {
- "action": "string",
- "actor_email": "string",
- "actor_user_id": "d6ed4497-4325-4995-9f49-e288b7192e46",
- "created_at": "2019-08-24T14:15:22Z",
- "diff": { },
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "request_id": "string",
- "target_id": "string",
- "target_table": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
], - "page": 1,
- "page_size": 1,
- "total": 0
}Actor User Id (string) or Actor User Id (null) (Actor User Id) | |
Target Table (string) or Target Table (null) (Target Table) | |
Action (string) or Action (null) (Action) | |
From (string) or From (null) (From) | |
To (string) or To (null) (To) | |
Q (string) or Q (null) (Q) | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "has_more": true,
- "items": [
- {
- "action": "string",
- "actor_email": "string",
- "actor_user_id": "d6ed4497-4325-4995-9f49-e288b7192e46",
- "created_at": "2019-08-24T14:15:22Z",
- "diff": { },
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "request_id": "string",
- "target_id": "string",
- "target_table": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
], - "page": 1,
- "page_size": 1,
- "total": 0
}Actor User Id (string) or Actor User Id (null) (Actor User Id) | |
Target Table (string) or Target Table (null) (Target Table) | |
Action (string) or Action (null) (Action) | |
From (string) or From (null) (From) | |
To (string) or To (null) (To) | |
Q (string) or Q (null) (Q) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Actor User Id (string) or Actor User Id (null) (Actor User Id) | |
Target Table (string) or Target Table (null) (Target Table) | |
Action (string) or Action (null) (Action) | |
From (string) or From (null) (From) | |
To (string) or To (null) (To) | |
Q (string) or Q (null) (Q) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}X-Confirm-Restore (string) or X-Confirm-Restore (null) (X-Confirm-Restore) | |
Content-Length (integer) or Content-Length (null) (Content-Length) |
| archive required | string <application/octet-stream> (Archive) tar.gz produced by GET /download. |
{- "message": "string",
- "task_id": "string"
}X-Confirm-Restore (string) or X-Confirm-Restore (null) (X-Confirm-Restore) | |
Content-Length (integer) or Content-Length (null) (Content-Length) |
| archive required | string <application/octet-stream> (Archive) tar.gz produced by GET /download. |
{- "message": "string",
- "task_id": "string"
}| name required | string (Name) Backup directory name. |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| name required | string (Name) Backup directory name. |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}{- "collected_at": "2019-08-24T14:15:22Z",
- "items": [
- {
- "error": "string",
- "free_bytes": 0,
- "name": "workspace",
- "path": "string",
- "status": "ok",
- "threshold_critical": 90,
- "threshold_warning": 80,
- "total_bytes": 0,
- "used_bytes": 0,
- "used_pct": 100
}
]
}{- "collected_at": "2019-08-24T14:15:22Z",
- "items": [
- {
- "error": "string",
- "free_bytes": 0,
- "name": "workspace",
- "path": "string",
- "status": "ok",
- "threshold_critical": 90,
- "threshold_warning": 80,
- "total_bytes": 0,
- "used_bytes": 0,
- "used_pct": 100
}
]
}{- "cleared": 0,
- "duration_ms": 0,
- "enabled": true,
- "eol_flagged_total": 0,
- "feed_host": "string",
- "last_attempt_at": "2019-08-24T14:15:22Z",
- "last_result": "synced",
- "last_synced_at": "2019-08-24T14:15:22Z",
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "product_count": 0,
- "refresh_enabled": true,
- "rule_count": 0,
- "skipped_reason": "string",
- "snapshot_date": "2019-08-24",
- "snapshot_origin": "vendored",
- "stamped": 0
}{- "cleared": 0,
- "duration_ms": 0,
- "enabled": true,
- "eol_flagged_total": 0,
- "feed_host": "string",
- "last_attempt_at": "2019-08-24T14:15:22Z",
- "last_result": "synced",
- "last_synced_at": "2019-08-24T14:15:22Z",
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "product_count": 0,
- "refresh_enabled": true,
- "rule_count": 0,
- "skipped_reason": "string",
- "snapshot_date": "2019-08-24",
- "snapshot_origin": "vendored",
- "stamped": 0
}{- "components": [
- {
- "detail": "string",
- "detail_code": "string",
- "detail_params": {
- "property1": "string",
- "property2": "string"
}, - "name": "postgres",
- "status": "ok",
- "value": 0
}
], - "updated_at": "2019-08-24T14:15:22Z"
}{- "components": [
- {
- "detail": "string",
- "detail_code": "string",
- "detail_params": {
- "property1": "string",
- "property2": "string"
}, - "name": "postgres",
- "status": "ok",
- "value": 0
}
], - "updated_at": "2019-08-24T14:15:22Z"
}{- "delisted": 0,
- "duration_ms": 0,
- "enabled": true,
- "feed_count": 0,
- "feed_host": "string",
- "kev_flagged_total": 0,
- "last_attempt_at": "2019-08-24T14:15:22Z",
- "last_result": "synced",
- "last_synced_at": "2019-08-24T14:15:22Z",
- "listed": 0,
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "skipped_reason": "string"
}{- "delisted": 0,
- "duration_ms": 0,
- "enabled": true,
- "feed_count": 0,
- "feed_host": "string",
- "kev_flagged_total": 0,
- "last_attempt_at": "2019-08-24T14:15:22Z",
- "last_result": "synced",
- "last_synced_at": "2019-08-24T14:15:22Z",
- "listed": 0,
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "skipped_reason": "string"
}{- "ecosystems": [
- "string"
], - "enabled": true,
- "flagged_total": 0,
- "last_attempt_at": "2019-08-24T14:15:22Z",
- "last_result": "synced",
- "last_synced_at": "2019-08-24T14:15:22Z",
- "newly_flagged": 0,
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "purl_count": 0,
- "refresh_enabled": true,
- "skipped_reason": "string",
- "snapshot_date": "2019-08-24",
- "snapshot_stale": false,
- "stamped": 0
}{- "ecosystems": [
- "string"
], - "enabled": true,
- "flagged_total": 0,
- "last_attempt_at": "2019-08-24T14:15:22Z",
- "last_result": "synced",
- "last_synced_at": "2019-08-24T14:15:22Z",
- "newly_flagged": 0,
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "purl_count": 0,
- "refresh_enabled": true,
- "skipped_reason": "string",
- "snapshot_date": "2019-08-24",
- "snapshot_stale": false,
- "stamped": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_personal": true,
- "name": "string",
- "slug": "string",
- "team_count": 0
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_personal": true,
- "name": "string",
- "slug": "string",
- "team_count": 0
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| organization_id required | string <uuid> (Organization Id) |
{- "items": [
- {
- "allowed": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "registry_host": "string",
- "username": "string"
}
]
}| organization_id required | string <uuid> (Organization Id) |
{- "items": [
- {
- "allowed": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "registry_host": "string",
- "username": "string"
}
]
}| organization_id required | string <uuid> (Organization Id) |
| password required | string (Password) non-empty Registry password or token. Stored as Fernet ciphertext and never returned by any route. |
| registry_host required | string (Registry Host) [ 1 .. 255 ] characters Registry host as it appears in an image reference: |
| username required | string (Username) [ 1 .. 255 ] characters |
{- "password": "string",
- "registry_host": "string",
- "username": "string"
}{- "allowed": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "registry_host": "string",
- "username": "string"
}| organization_id required | string <uuid> (Organization Id) |
| password required | string (Password) non-empty Registry password or token. Stored as Fernet ciphertext and never returned by any route. |
| registry_host required | string (Registry Host) [ 1 .. 255 ] characters Registry host as it appears in an image reference: |
| username required | string (Username) [ 1 .. 255 ] characters |
{- "password": "string",
- "registry_host": "string",
- "username": "string"
}{- "allowed": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "registry_host": "string",
- "username": "string"
}| organization_id required | string <uuid> (Organization Id) |
| credential_id required | string <uuid> (Credential Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| organization_id required | string <uuid> (Organization Id) |
| credential_id required | string <uuid> (Credential Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| organization_id required | string <uuid> (Organization Id) |
{- "items": [
- {
- "auth_scheme": "string",
- "host": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "username": "string"
}
]
}| organization_id required | string <uuid> (Organization Id) |
{- "items": [
- {
- "auth_scheme": "string",
- "host": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "username": "string"
}
]
}| organization_id required | string <uuid> (Organization Id) |
| api_token required | string (Api Token) non-empty Tracker API token or password. Stored as Fernet ciphertext and never returned by any route. |
| auth_scheme | string (Auth Scheme) Default: "jira_basic" One of ['jira_basic']. |
| host required | string (Host) [ 1 .. 255 ] characters Tracker host as it appears in a finding's |
Username (string) or Username (null) (Username) The tracker account's login (Jira Cloud: its email). Required for |
{- "api_token": "string",
- "auth_scheme": "jira_basic",
- "host": "string",
- "username": "string"
}{- "auth_scheme": "string",
- "host": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "username": "string"
}| organization_id required | string <uuid> (Organization Id) |
| api_token required | string (Api Token) non-empty Tracker API token or password. Stored as Fernet ciphertext and never returned by any route. |
| auth_scheme | string (Auth Scheme) Default: "jira_basic" One of ['jira_basic']. |
| host required | string (Host) [ 1 .. 255 ] characters Tracker host as it appears in a finding's |
Username (string) or Username (null) (Username) The tracker account's login (Jira Cloud: its email). Required for |
{- "api_token": "string",
- "auth_scheme": "jira_basic",
- "host": "string",
- "username": "string"
}{- "auth_scheme": "string",
- "host": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "username": "string"
}| organization_id required | string <uuid> (Organization Id) |
| credential_id required | string <uuid> (Credential Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| organization_id required | string <uuid> (Organization Id) |
| credential_id required | string <uuid> (Credential Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
Status (string) or Status (null) (Status) | |
Kind (string) or Kind (null) (Kind) | |
Project (string) or Project (null) (Project) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "duration_seconds": 0,
- "error_message": "string",
- "finished_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "page": 1,
- "page_size": 1,
- "total": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
Status (string) or Status (null) (Status) | |
Kind (string) or Kind (null) (Kind) | |
Project (string) or Project (null) (Project) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "duration_seconds": 0,
- "error_message": "string",
- "finished_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "page": 1,
- "page_size": 1,
- "total": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
Search (string) or Search (null) (Search) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "member_count": 0,
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
Search (string) or Search (null) (Search) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "member_count": 0,
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}Description (string) or Description (null) (Description) | |
| name required | string (Name) [ 1 .. 255 ] characters |
Organization Id (string) or Organization Id (null) (Organization Id) Which Organization the team belongs to. Required once a deployment has more than one (self-signup creates a personal Organization per user, so a demo SaaS deployment usually does): the create call refuses with 422 rather than silently guessing. Omit on a single-organization deployment; see GET /v1/admin/organizations to find the id. | |
| slug required | string (Slug) [ 1 .. 64 ] characters |
{- "description": "string",
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "slug": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}Description (string) or Description (null) (Description) | |
| name required | string (Name) [ 1 .. 255 ] characters |
Organization Id (string) or Organization Id (null) (Organization Id) Which Organization the team belongs to. Required once a deployment has more than one (self-signup creates a personal Organization per user, so a demo SaaS deployment usually does): the create call refuses with 422 rather than silently guessing. Omit on a single-organization deployment; see GET /v1/admin/organizations to find the id. | |
| slug required | string (Slug) [ 1 .. 64 ] characters |
{- "description": "string",
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "slug": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| group_id required | string <uuid> (Group Id) |
New Parent Id (string) or New Parent Id (null) (New Parent Id) The group to move this group (and its whole subtree) under. Null moves the group to the root of its own organization. | |
Any of string <uuid> (New Parent Id) The group to move this group (and its whole subtree) under. Null moves the group to the root of its own organization. | |
{- "new_parent_id": "95240cae-bfce-4d31-9b0f-a42763cd03ac"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| group_id required | string <uuid> (Group Id) |
New Parent Id (string) or New Parent Id (null) (New Parent Id) The group to move this group (and its whole subtree) under. Null moves the group to the root of its own organization. | |
Any of string <uuid> (New Parent Id) The group to move this group (and its whole subtree) under. Null moves the group to the root of its own organization. | |
{- "new_parent_id": "95240cae-bfce-4d31-9b0f-a42763cd03ac"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| parent_group_id required | string <uuid> (Parent Group Id) |
Description (string) or Description (null) (Description) | |
| name required | string (Name) [ 1 .. 255 ] characters |
| slug required | string (Slug) [ 1 .. 64 ] characters |
{- "description": "string",
- "name": "string",
- "slug": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| parent_group_id required | string <uuid> (Parent Group Id) |
Description (string) or Description (null) (Description) | |
| name required | string (Name) [ 1 .. 255 ] characters |
| slug required | string (Slug) [ 1 .. 64 ] characters |
{- "description": "string",
- "name": "string",
- "slug": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| team_id required | string <uuid> (Team Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| team_id required | string <uuid> (Team Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
Description (string) or Description (null) (Description) | |
Name (string) or Name (null) (Name) | |
Slug (string) or Slug (null) (Slug) |
{- "description": "string",
- "name": "string",
- "slug": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
Description (string) or Description (null) (Description) | |
Name (string) or Name (null) (Name) | |
Slug (string) or Slug (null) (Slug) |
{- "description": "string",
- "name": "string",
- "slug": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| role required | string (Role) One of team_admin, developer or viewer. |
| user_id required | string <uuid> (User Id) |
{- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| role required | string (Role) One of team_admin, developer or viewer. |
| user_id required | string <uuid> (User Id) |
{- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "members": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}{- "cache_dir": "string",
- "db_size_bytes": 0,
- "db_version": "string",
- "freshness": "fresh",
- "last_update": "2019-08-24T14:15:22Z",
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "refresh_interval_hours": 1,
- "repository": "string",
- "vuln_count": 0
}{- "cache_dir": "string",
- "db_size_bytes": 0,
- "db_version": "string",
- "freshness": "fresh",
- "last_update": "2019-08-24T14:15:22Z",
- "next_refresh_at": "2019-08-24T14:15:22Z",
- "refresh_interval_hours": 1,
- "repository": "string",
- "vuln_count": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
Role (string) or Role (null) (Role) | |
Active (boolean) or Active (null) (Active) | |
Search (string) or Search (null) (Search) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "role": "super_admin",
- "team_count": 0
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
Role (string) or Role (null) (Role) | |
Active (boolean) or Active (null) (Active) | |
Search (string) or Search (null) (Search) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "role": "super_admin",
- "team_count": 0
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| email required | string <email> (Email) |
Full Name (string) or Full Name (null) (Full Name) | |
Password (string) or Password (null) (Password) Omit on a deployment where people sign in through an identity provider: the account is created with no password set, so it cannot be signed into until somebody sets one through the reset flow. A password given here is held to the same policy as one chosen at signup. | |
Role (string) or Role (null) (Role) Their grade on that team. Omitted follows the deployment's DEFAULT_MEMBER_ROLE. super_admin is not assignable here. | |
Team Id (string) or Team Id (null) (Team Id) The team to put them on. Omitted leaves them on no team, which is a real state: they can sign in and see nothing until somebody adds them. |
{- "email": "user@example.com",
- "full_name": "string",
- "password": "stringst",
- "role": "group_admin",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}| email required | string <email> (Email) |
Full Name (string) or Full Name (null) (Full Name) | |
Password (string) or Password (null) (Password) Omit on a deployment where people sign in through an identity provider: the account is created with no password set, so it cannot be signed into until somebody sets one through the reset flow. A password given here is held to the same policy as one chosen at signup. | |
Role (string) or Role (null) (Role) Their grade on that team. Omitted follows the deployment's DEFAULT_MEMBER_ROLE. super_admin is not assignable here. | |
Team Id (string) or Team Id (null) (Team Id) The team to put them on. Omitted leaves them on no team, which is a real state: they can sign in and see nothing until somebody adds them. |
{- "email": "user@example.com",
- "full_name": "string",
- "password": "stringst",
- "role": "group_admin",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}required | Array of objects (Users) [ 1 .. 500 ] items | ||||||||||
Array ([ 1 .. 500 ] items)
| |||||||||||
{- "users": [
- {
- "email": "user@example.com",
- "full_name": "string",
- "password": "stringst",
- "role": "group_admin",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
]
}{- "failed": 0,
- "results": [
- {
- "detail": "string",
- "identifier": "string",
- "index": 0,
- "reason": "string",
- "status": "created",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "succeeded": 0,
- "total": 0
}required | Array of objects (Users) [ 1 .. 500 ] items | ||||||||||
Array ([ 1 .. 500 ] items)
| |||||||||||
{- "users": [
- {
- "email": "user@example.com",
- "full_name": "string",
- "password": "stringst",
- "role": "group_admin",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
]
}{- "failed": 0,
- "results": [
- {
- "detail": "string",
- "identifier": "string",
- "index": 0,
- "reason": "string",
- "status": "created",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "succeeded": 0,
- "total": 0
}| user_ids required | Array of strings <uuid> (User Ids) [ 1 .. 500 ] items [ items <uuid > ] |
{- "user_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}{- "failed": 0,
- "results": [
- {
- "detail": "string",
- "identifier": "string",
- "index": 0,
- "reason": "string",
- "status": "created",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "succeeded": 0,
- "total": 0
}| user_ids required | Array of strings <uuid> (User Ids) [ 1 .. 500 ] items [ items <uuid > ] |
{- "user_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
]
}{- "failed": 0,
- "results": [
- {
- "detail": "string",
- "identifier": "string",
- "index": 0,
- "reason": "string",
- "status": "created",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "succeeded": 0,
- "total": 0
}| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}Undoes somebody's second-factor enrolment: the flag, the secret, the replay counter and every unused recovery code, with existing sessions ended.
This exists because losing an authenticator is the ordinary failure of a second factor, and the alternatives do not cover it. A password reset cannot: unlocking the factor by mailbox would reduce it to owning the mailbox, which is what the first factor already proves. Recovery codes do, for anybody who kept them.
-- What this does not protect against ------------------------------------
A compromised super admin. That is not new, and it is not created here: the same account can already change roles and create users, so it can mint itself a fresh super admin with no second factor. What this adds is the ability to impersonate one specific existing person, and the notification below is what narrows that: somebody who did not ask for their factor to be cleared finds out that it was.
Deliberately not two-person: an unlock is reversible, since the owner can enrol again, and making somebody who is locked out wait for a second approver costs more than it buys.
| user_id required | string <uuid> (User Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Undoes somebody's second-factor enrolment: the flag, the secret, the replay counter and every unused recovery code, with existing sessions ended.
This exists because losing an authenticator is the ordinary failure of a second factor, and the alternatives do not cover it. A password reset cannot: unlocking the factor by mailbox would reduce it to owning the mailbox, which is what the first factor already proves. Recovery codes do, for anybody who kept them.
-- What this does not protect against ------------------------------------
A compromised super admin. That is not new, and it is not created here: the same account can already change roles and create users, so it can mint itself a fresh super admin with no second factor. What this adds is the ability to impersonate one specific existing person, and the notification below is what narrows that: somebody who did not ask for their factor to be cleared finds out that it was.
Deliberately not two-person: an unlock is reversible, since the owner can enrol again, and making somebody who is locked out wait for a second approver costs more than it buys.
| user_id required | string <uuid> (User Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}| user_id required | string <uuid> (User Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}Issues a one-shot reset token (bcrypt-hashed in storage) and returns 204.
A follow-up change wires the SMTP / Slack delivery channel. Until then
the plaintext token is generated, persisted as a hash, audit-logged via
the listener (which masks the hash to ***), and discarded.
-- Account-enumeration semantics ------------------------------------------
This endpoint returns 404 when user_id does not exist. That IS an
enumeration oracle in isolation, but it is acceptable HERE because the
route is super-admin-gated by require_super_admin_or_404 — any
caller who can reach this code path is already authorised to read the
full user list (GET /v1/admin/users), so the 404 leaks no
information they did not already have. The trust boundary is ABOVE this
endpoint, not at it.
The PUBLIC password-reset flow ("forgot password") MUST NOT copy this 404-on-miss pattern. That endpoint is unauthenticated, so a 404 vs. 204 split there would let an attacker enumerate registered emails (CWE-204 Observable Response Discrepancy). The public flow returns a uniform 204 regardless of whether the email exists, with the actual reset email sent only when a match is found.
| user_id required | string <uuid> (User Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Issues a one-shot reset token (bcrypt-hashed in storage) and returns 204.
A follow-up change wires the SMTP / Slack delivery channel. Until then
the plaintext token is generated, persisted as a hash, audit-logged via
the listener (which masks the hash to ***), and discarded.
-- Account-enumeration semantics ------------------------------------------
This endpoint returns 404 when user_id does not exist. That IS an
enumeration oracle in isolation, but it is acceptable HERE because the
route is super-admin-gated by require_super_admin_or_404 — any
caller who can reach this code path is already authorised to read the
full user list (GET /v1/admin/users), so the 404 leaks no
information they did not already have. The trust boundary is ABOVE this
endpoint, not at it.
The PUBLIC password-reset flow ("forgot password") MUST NOT copy this 404-on-miss pattern. That endpoint is unauthenticated, so a 404 vs. 204 split there would let an attacker enumerate registered emails (CWE-204 Observable Response Discrepancy). The public flow returns a uniform 204 regardless of whether the email exists, with the actual reset email sent only when a match is found.
| user_id required | string <uuid> (User Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| user_id required | string <uuid> (User Id) |
| role required | string (Role) One of super_admin / group_admin / developer. |
Team Id (string) or Team Id (null) (Team Id) Required when role is group_admin or developer; ignored for super_admin. |
{- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}| user_id required | string <uuid> (User Id) |
| role required | string (Role) One of super_admin / group_admin / developer. |
Team Id (string) or Team Id (null) (Team Id) Required when role is group_admin or developer; ignored for super_admin. |
{- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "is_superuser": true,
- "last_login_at": "2019-08-24T14:15:22Z",
- "memberships": [
- {
- "role": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "mfa_enabled": false,
- "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}Clears the per-address failed sign-in count so the person can try again.
Failed sign-ins are counted per address, and a refusal lasts until its window runs out. That is a slowdown for somebody guessing and an inconvenience for somebody who mistyped, but it is also a way to keep an account's owner out on purpose: anybody who knows an email can supply failures for it. Two things answer that. Completing a password reset clears the count, which needs the inbox and so cannot be blocked by the person doing the guessing. This is the other, for somebody who has lost access to that inbox.
It is not otherwise recoverable by hand. The counter is keyed by an HMAC of the address, which is deliberate -- Redis then holds no list of who has tried to sign in -- and the cost is that an operator cannot find or delete one person's key without the deployment secret and a script.
Super-admin only, and audited: this acts on somebody else's account, and clearing a count during an attack is a decision somebody should be able to review afterwards.
Returns 404 for an unknown user, on the same reasoning as the sibling password-reset route: the caller can already list every user, so the 404 tells them nothing new. The public sign-in path must not copy it.
| user_id required | string <uuid> (User Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Clears the per-address failed sign-in count so the person can try again.
Failed sign-ins are counted per address, and a refusal lasts until its window runs out. That is a slowdown for somebody guessing and an inconvenience for somebody who mistyped, but it is also a way to keep an account's owner out on purpose: anybody who knows an email can supply failures for it. Two things answer that. Completing a password reset clears the count, which needs the inbox and so cannot be blocked by the person doing the guessing. This is the other, for somebody who has lost access to that inbox.
It is not otherwise recoverable by hand. The counter is keyed by an HMAC of the address, which is deliberate -- Redis then holds no list of who has tried to sign in -- and the cost is that an operator cannot find or delete one person's key without the deployment secret and a script.
Super-admin only, and audited: this acts on somebody else's account, and clearing a count during an attack is a decision somebody should be able to review afterwards.
Returns 404 for an unknown user, on the same reasoning as the sibling password-reset route: the caller can already list every user, so the 404 tells them nothing new. The public sign-in path must not copy it.
| user_id required | string <uuid> (User Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Scope (string) or Scope (null) (Scope) | |
Team Id (string) or Team Id (null) (Team Id) | |
Project Id (string) or Project Id (null) (Project Id) | |
| include_revoked | boolean (Include Revoked) Default: false |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_email": "string",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "expires_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "key_prefix": "string",
- "last_used_at": "2019-08-24T14:15:22Z",
- "name": "string",
- "permission_breadth": "read_write",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "revoked_at": "2019-08-24T14:15:22Z",
- "scope": "org",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}Expires In Days (integer) or Expires In Days (null) (Expires In Days) Optional TTL in days. The key stops authenticating after this many days. Omit for a non-expiring key (CI keys should set one and rotate). Max 1825 (5 years). | |
| name required | string (Name) [ 1 .. 100 ] characters |
| permission_breadth | string (Permission Breadth) Default: "read_only" Enum: "read_write" "read_only" What the key may do: 'read_only' (the default) or 'read_write'. A read-only key is refused every request that changes something, so a pipeline that just reads results cannot start a scan. Keys issued before this existed are read-write and stay that way. |
Project Id (string) or Project Id (null) (Project Id) | |
| scope required | string (Scope) Enum: "org" "team" "project" |
Service Account Id (string) or Service Account Id (null) (Service Account Id) Issue the key to an automation identity instead of to yourself. The key then lives as long as that identity does, rather than stopping when you are deactivated. Omit for a personal key, which keeps today's behaviour exactly. | |
Team Id (string) or Team Id (null) (Team Id) |
{- "expires_in_days": 1,
- "name": "string",
- "permission_breadth": "read_write",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "scope": "org",
- "service_account_id": "81f92c7b-60ae-411e-bc6f-e2dc93db8886",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}{- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "expires_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "key_prefix": "string",
- "name": "string",
- "permission_breadth": "read_write",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "raw_key": "string",
- "scope": "org",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}| api_key_id required | string <uuid> (Api Key Id) |
| permission_breadth required | string (Permission Breadth) The only accepted value. Breadth narrows and never widens: a key that has been sitting in a CI log should not be handed more privilege than it was issued with. Value: "read_only" |
{- "permission_breadth": "read_only"
}{- "created_at": "2019-08-24T14:15:22Z",
- "created_by_email": "string",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "expires_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "key_prefix": "string",
- "last_used_at": "2019-08-24T14:15:22Z",
- "name": "string",
- "permission_breadth": "read_write",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "revoked_at": "2019-08-24T14:15:22Z",
- "scope": "org",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}Status (string) or Status (null) (Status) Single status or a comma-separated list of statuses (e.g. | |
Team Id (string) or Team Id (null) (Team Id) | |
Project Id (string) or Project Id (null) (Project Id) Narrow the queue to one project. Applied after the team gate, so a project outside the caller's teams returns an empty page rather than an error, exactly as an unknown id does. | |
Requested By User Id (string) or Requested By User Id (null) (Requested By User Id) | |
From Dt (string) or From Dt (null) (From Dt) | |
To Dt (string) or To Dt (null) (To Dt) | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "component_name": "string",
- "component_purl": "string",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "requested_at": "2019-08-24T14:15:22Z",
- "requested_by_name": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "pending",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "version": 0
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| component_id required | string <uuid> (Component Id) |
| project_id required | string <uuid> (Project Id) |
{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9"
}{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "component_name": "string",
- "component_purl": "string",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "requested_at": "2019-08-24T14:15:22Z",
- "requested_by_name": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "pending",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "version": 0
}| approval_id required | string <uuid> (Approval Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| approval_id required | string <uuid> (Approval Id) |
{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "component_name": "string",
- "component_purl": "string",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "requested_at": "2019-08-24T14:15:22Z",
- "requested_by_name": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "pending",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "version": 0
}| approval_id required | string <uuid> (Approval Id) |
If-Match (string) or If-Match (null) (If-Match) |
| action required | string (Action) Enum: "under_review" "approved" "rejected" |
Decision Note (string) or Decision Note (null) (Decision Note) |
{- "action": "under_review",
- "decision_note": "string"
}{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "component_name": "string",
- "component_purl": "string",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "requested_at": "2019-08-24T14:15:22Z",
- "requested_by_name": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "pending",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "version": 0
}Actor User Id (string) or Actor User Id (null) (Actor User Id) | |
Target Table (string) or Target Table (null) (Target Table) | |
Action (string) or Action (null) (Action) | |
From (string) or From (null) (From) | |
To (string) or To (null) (To) | |
Q (string) or Q (null) (Q) | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "has_more": true,
- "items": [
- {
- "action": "string",
- "actor_email": "string",
- "actor_user_id": "d6ed4497-4325-4995-9f49-e288b7192e46",
- "created_at": "2019-08-24T14:15:22Z",
- "diff": { },
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "request_id": "string",
- "target_id": "string",
- "target_table": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
], - "page": 1,
- "page_size": 1,
- "total": 0
}Component Stack (string) or Component Stack (null) (Component Stack) React's | |
| message required | string (Message) [ 1 .. 2000 ] characters
|
Stack (string) or Stack (null) (Stack)
| |
| url required | string (Url) [ 1 .. 2000 ] characters
|
{- "component_stack": "string",
- "message": "string",
- "stack": "string",
- "url": "string"
}{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| component_id required | string <uuid> (Component Id) |
{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "created_at": "2019-08-24T14:15:22Z",
- "currency_latest": "string",
- "currency_latest_release_date": "2019-08-24",
- "currency_state": "current",
- "dependency_scope": "required",
- "depth": 0,
- "direct": false,
- "eol_cycle": "string",
- "eol_date": "2019-08-24",
- "eol_product": "string",
- "eol_source": "string",
- "eol_state": "eol",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license": "string",
- "license_category": "forbidden",
- "malicious_id": "string",
- "malicious_source": "string",
- "malicious_state": "flagged",
- "name": "string",
- "obligations": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "license": "string",
- "link": "string",
- "text": "string"
}
], - "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "purl": "string",
- "raw_data": { },
- "severity_max": "critical",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": "string",
- "vulnerabilities": [
- {
- "cve_id": "string",
- "cvss": 0,
- "description": "string",
- "epss_percentile": 1,
- "epss_score": 1,
- "fixed_version": "string",
- "severity": "string",
- "title": "string"
}
]
}Pending approvals, KEV findings against their CISA deadline, projects the build gate would block, and projects nothing has scanned recently.
Same scoping contract as /summary: the caller's identity is the scope,
enforced in the service through the shared accessible-projects helper. The
gate bucket aggregates the gate's inputs rather than calling
evaluate_gate per project — see services.action_queue_service for
why, and for the parity test that keeps the two in agreement.
Rate limited per actor. BUCKET_LIMIT caps the rows returned but not
the work done: the aggregates scan every open finding across the caller's
accessible projects, so cost grows with portfolio size even though query
count does not. Without a limit, one token could hold the connection pool
on a large deployment.
{- "gate_blocked": [
- {
- "critical_cve_count": 0,
- "epss_gate_count": 0,
- "forbidden_license_count": 0,
- "malicious_component_count": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af"
}
], - "kev_sla": {
- "due_soon": 0,
- "overdue": 0
}, - "pending_approvals": 0,
- "stale_projects": [
- {
- "last_succeeded_at": "2019-08-24T14:15:22Z",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string"
}
]
}Every project the caller can see, grouped by the team that owns it.
The grouping is the point: a list answers "which project is worst", this answers "which team is carrying the risk". Same scoping contract as the other three — the caller's identity is the scope, and team names are read only for teams that own a visible project, so a caller cannot enumerate the organisation's teams through an empty row.
Both the per-team and the overall project caps are display limits, and the response reports what they cut: a grid that silently showed a subset would invite the reader to conclude the rest is clean.
{- "project_count": 0,
- "shown_project_count": 0,
- "shown_team_count": 0,
- "team_count": 0,
- "teams": [
- {
- "project_count": 0,
- "projects": [
- {
- "critical": 0,
- "high": 0,
- "last_scan_at": "2019-08-24T14:15:22Z",
- "low": 0,
- "medium": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "scanned": true
}
], - "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string"
}
], - "truncated": true
}Aggregate counts (projects, scans, severities, licenses, approvals) plus the 10 most recent scans, scoped to the caller's accessible projects.
Rate limited per actor on the same bucket and budget as the other three
dashboard routes (/action-queue, /trends, /portfolio): this
route used to be the one dashboard endpoint without a limiter, which made
it the cheapest way to repeatedly re-run the portfolio-wide aggregate.
{- "license_category_counts": {
- "conditional": 4,
- "permissive": 180,
- "prohibited": 1,
- "unknown": 12
}, - "pending_approvals_count": 2,
- "project_count": 7,
- "recent_scans": [
- {
- "finished_at": "2026-05-25T09:14:00Z",
- "kind": "source",
- "project_id": "9a2b7e10-0000-0000-0000-000000000002",
- "project_name": "payments-api",
- "scan_id": "3f1d8c2a-0000-0000-0000-000000000001",
- "status": "succeeded"
}
], - "scan_status_counts": {
- "failed": 2,
- "queued": 1,
- "running": 0,
- "succeeded": 12
}, - "vulnerability_severity_counts": {
- "critical": 3,
- "high": 9,
- "info": 5,
- "low": 41,
- "medium": 22
}
}New and resolved exposures per day, plus the standing critical / KEV counts, over the caller's accessible projects.
days is a closed set rather than a free integer: an arbitrary window
would let one request walk years of scan history, and the service raises
on anything outside it, so a widened query parameter cannot quietly become
an unbounded scan. It is an IntEnum rather than a literal of ints
because a query string arrives as "7" and a literal refuses to coerce
it — the literal spelling rejected every window a caller asked for while
still honouring the default, which is a shape no test of the default can
see.
Same scoping contract as /summary — the caller's identity is the
scope, enforced in the service through the shared accessible-projects
helper. Rate limited per actor for the same reason as the action queue:
query count is fixed but the exposure sets read grow with the portfolio.
| days | integer (TrendWindow) Default: 30 Enum: 7 30 90 Window length in days, inclusive of today. |
{- "end_date": "2019-08-24",
- "period_days": 0,
- "points": [
- {
- "critical_open": 0,
- "date": "2019-08-24",
- "kev_open": 0,
- "new_findings": 0,
- "resolved_findings": 0,
- "scan_count": 0
}
], - "project_count": 0,
- "start_date": "2019-08-24",
- "totals": {
- "new_findings": 0,
- "resolved_findings": 0
}
}| advisory_id required | string (Advisory Id) [ 1 .. 64 ] characters |
{- "advisory_id": "GHSA-f23m-r3pf-42rh",
- "aliases": [
- "CVE-2025-13465"
], - "cvss3_score": 6.5,
- "cvss3_vector": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:L",
- "found": true,
- "title": "lodash vulnerable to Prototype Pollution"
}| ecosystem required | string (Ecosystem) <= 64 characters One of: cargo, go, maven, npm, nuget, pypi. |
| name required | string (Name) [ 1 .. 255 ] characters |
{- "advisory_count": 0,
- "advisory_ids": [ ],
- "ecosystem": "npm",
- "found": true,
- "internal_projects": [ ],
- "licenses": [
- "MIT"
], - "name": "lodash",
- "purl": "pkg:npm/lodash",
- "source_repo_url": "git+https://github.com/lodash/lodash.git",
- "version": "4.18.1"
}Resolve the policy, then fill the gaps the way the gate itself does.
A value shown here without saying where it came from invites the wrong
edit: an operator who sees a threshold and assumes their group set it will
look for a row that does not exist. sources names the group(s) or
organization that supplied each value, with deployment for the ones
no policy decided. sources_legacy is the deprecated pre-group-hierarchy
string form of the same information (see its own docstring).
This endpoint used to resolve and return a project's policy with no
team/group membership check at all -- require_role("viewer") is a
coarse, route-level floor, not a project-scoped one. Once sources
started naming the actual contributing groups, that gap widened from
leaking "a threshold is team-set" to leaking real group names and the
ancestor chain to any authenticated stranger. Hidden rather than
refused, same as get_team_policy's own scope check below: existence
of another organization's project/group is not this caller's business
either.
| project_id required | string <uuid> (Project Id) |
{- "approval_required_statuses": [
- "string"
], - "epss_data_available": true,
- "epss_last_synced_at": "2019-08-24T14:15:22Z",
- "epss_refresh_enabled": false,
- "epss_scored_cves": 0,
- "epss_threshold": 0,
- "malicious_blocks": true,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "reachable_critical_only": true,
- "sources": {
- "property1": {
- "group_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "group_paths": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "path": [
- "string"
]
}
], - "organization_contributed": false,
- "scope": "group"
}, - "property2": {
- "group_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "group_paths": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "path": [
- "string"
]
}
], - "organization_contributed": false,
- "scope": "group"
}
}, - "sources_legacy": {
- "property1": "team",
- "property2": "team"
}
}Deployment-scoped, so the policy editor can qualify a threshold it shows.
Not derived from a project or a scan: the question an administrator has while setting a threshold is whether this deployment collects EPSS, and that has one answer regardless of which project they came from. The per-scan version of the question rides on the gate result instead.
No path parameter, so nothing to authorize beyond being a signed-in reader: the response describes the deployment's own configuration and carries no project, team or finding data.
{- "available": true,
- "last_synced_at": "2019-08-24T14:15:22Z",
- "refresh_enabled": true,
- "scored_cves": 0
}| organization_id required | string <uuid> (Organization Id) |
Array of Approval Required Statuses (strings) or Approval Required Statuses (null) (Approval Required Statuses) Finding statuses one person may not reach alone. Reaching one of these opens a request that somebody else decides. Null or empty means every transition stays a single action. | |
Epss Threshold (number) or Epss Threshold (null) (Epss Threshold) Block when an open finding's exploit-prediction score reaches this. Null leaves the condition off, which is the behaviour with no policy. | |
Malicious Blocks (boolean) or Malicious Blocks (null) (Malicious Blocks) Whether a package the malicious snapshot flags blocks the build. Unlike the other two this is on by default, so a policy row only ever turns it off deliberately. | |
Name (string) or Name (null) (Name) Label for the policy. The scope is its identity; this is for the UI. | |
Reachable Critical Only (boolean) or Reachable Critical Only (null) (Reachable Critical Only) Count only criticals an analyser proved reachable. This can only shrink the blocking set, never widen it, and it applies only to scans that were actually analysed. |
{- "approval_required_statuses": [
- "string"
], - "epss_threshold": 1,
- "malicious_blocks": true,
- "name": "string",
- "reachable_critical_only": true
}{- "approval_required_statuses": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "epss_threshold": 0,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "malicious_blocks": true,
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "reachable_critical_only": true,
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
{- "approval_required_statuses": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "epss_threshold": 0,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "malicious_blocks": true,
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "reachable_critical_only": true,
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
Array of Approval Required Statuses (strings) or Approval Required Statuses (null) (Approval Required Statuses) Finding statuses one person may not reach alone. Reaching one of these opens a request that somebody else decides. Null or empty means every transition stays a single action. | |
Epss Threshold (number) or Epss Threshold (null) (Epss Threshold) Block when an open finding's exploit-prediction score reaches this. Null leaves the condition off, which is the behaviour with no policy. | |
Malicious Blocks (boolean) or Malicious Blocks (null) (Malicious Blocks) Whether a package the malicious snapshot flags blocks the build. Unlike the other two this is on by default, so a policy row only ever turns it off deliberately. | |
Name (string) or Name (null) (Name) Label for the policy. The scope is its identity; this is for the UI. | |
Reachable Critical Only (boolean) or Reachable Critical Only (null) (Reachable Critical Only) Count only criticals an analyser proved reachable. This can only shrink the blocking set, never widen it, and it applies only to scans that were actually analysed. |
{- "approval_required_statuses": [
- "string"
], - "epss_threshold": 1,
- "malicious_blocks": true,
- "name": "string",
- "reachable_critical_only": true
}{- "approval_required_statuses": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "epss_threshold": 0,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "malicious_blocks": true,
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "reachable_critical_only": true,
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}Team Id (string) or Team Id (null) (Team Id) | |
| include_revoked | boolean (Include Revoked) Default: false |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "app_id": "string",
- "app_slug": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "has_private_key": true,
- "has_webhook_secret": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "revoked_at": "2019-08-24T14:15:22Z",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| team_id required | string <uuid> (Team Id) The team that owns this credential. |
| app_id required | string (App Id) [ 1 .. 64 ] characters |
App Slug (string) or App Slug (null) (App Slug) | |
| private_key required | string (Private Key) non-empty The GitHub App PEM private key (plaintext). Accepted ONCE at registration, encrypted at rest, and never returned. |
Webhook Secret (string) or Webhook Secret (null) (Webhook Secret) |
{- "app_id": "string",
- "app_slug": "string",
- "private_key": "string",
- "webhook_secret": "string"
}{- "app_id": "string",
- "app_slug": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "has_private_key": true,
- "has_webhook_secret": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "revoked_at": "2019-08-24T14:15:22Z",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}| credential_id required | string <uuid> (Credential Id) |
{- "app_id": "string",
- "app_slug": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "has_private_key": true,
- "has_webhook_secret": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "revoked_at": "2019-08-24T14:15:22Z",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}| credential_id required | string <uuid> (Credential Id) |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "account_login": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "credential_id": "13c40afa-2996-4a0c-b2e9-68fba9462242",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "installation_id": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "repository_full_name": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| credential_id required | string <uuid> (Credential Id) |
Account Login (string) or Account Login (null) (Account Login) | |
| installation_id required | string (Installation Id) [ 1 .. 64 ] characters |
Project Id (string) or Project Id (null) (Project Id) The TrustedOSS project this installation is opted-in to. | |
Repository Full Name (string) or Repository Full Name (null) (Repository Full Name) |
{- "account_login": "string",
- "installation_id": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "repository_full_name": "string"
}{- "account_login": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "credential_id": "13c40afa-2996-4a0c-b2e9-68fba9462242",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "installation_id": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "repository_full_name": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| credential_id required | string <uuid> (Credential Id) |
| installation_row_id required | string <uuid> (Installation Row Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Q (string) or Q (null) (Q) Flat, whole-tree name search. When set, | |
Parent Id (string) or Parent Id (null) (Parent Id) Drill-down mode (only consulted when | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "child_group_count": 0,
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "member_count": 0,
- "name": "string",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| group_id required | string <uuid> (Group Id) |
{- "ancestors": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "slug": "string"
}
], - "child_group_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "description": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "member_count": 0,
- "name": "string",
- "parent_group_id": "fe5e9949-7da4-4318-86fb-b3b64b2df380",
- "project_count": 0,
- "slug": "string",
- "stats": {
- "subtree_approvals_processed_count": 0,
- "subtree_new_member_count": 0,
- "subtree_scan_count": 0,
- "window_days": 30
}, - "updated_at": "2019-08-24T14:15:22Z"
}| group_id required | string <uuid> (Group Id) |
{- "direct": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "inherited": [
- {
- "email": "string",
- "full_name": "string",
- "is_service_account": false,
- "role": "string",
- "source_group_id": "58d74375-43ee-4b76-86bc-674c69391672",
- "source_group_name": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
]
}Project Id (string) or Project Id (null) (Project Id) | |
Array of Status (strings) or Status (null) (Status) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "purl": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}
], - "total": 0
}| justification required | string (Justification) >= 10 characters Why this package. The reviewer is being asked about something that is not in the codebase yet, so this is all they have. |
| project_id required | string <uuid> (Project Id) |
| purl required | string (Purl) [ 5 .. 512 ] characters The package, as a purl: 'pkg:npm/lodash', 'pkg:pypi/requests'. A purl and not a name, because it is what a later scan will match the answer against. |
{- "justification": "stringstri",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "purl": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "purl": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}| request_id required | string <uuid> (Request Id) |
Note (string) or Note (null) (Note) Optional reasoning, kept either way. | |
| status required | string (Status) under_review, approved or rejected. |
{- "note": "string",
- "status": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "purl": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}| limit | integer (Limit) [ 1 .. 200 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
Q (string) or Q (null) (Q) Substring match on package name or purl. LIKE metacharacters are escaped and matched literally. | |
Array of Package Type (strings) or Package Type (null) (Package Type) | |
Array of Severity (strings) or Severity (null) (Severity) Worst-severity buckets to keep. Unknown tokens are ignored. | |
Array of License Category (strings) or License Category (null) (License Category) | |
Eol (boolean) or Eol (null) (Eol) | |
Outdated (boolean) or Outdated (null) (Outdated) | |
| sort | string (Sort) ^(name|project_count|severity|license)$ Default: "project_count" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
{- "items": [
- {
- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "eol": true,
- "license_category_max": "forbidden",
- "name": "string",
- "outdated": true,
- "package_type": "string",
- "project_count": 0,
- "purl": "string",
- "severity_max": "critical",
- "version_count": 0,
- "versions": [
- "string"
], - "vulnerability_count": 0
}
], - "limit": 0,
- "offset": 0,
- "total": 0
}The same rows the list endpoint would return, without the paging.
The scope is the caller's own: the list service resolves which teams the actor can read and the export calls that same service, so a member of one team never receives another team's packages.
sort/order are still accepted and validated but no longer decide
the exported rows' order (#463): the export walks a fixed key (the
component id) instead, since this is the org-wide rollup, the export
most likely to reach a depth where OFFSET's cost matters.
Q (string) or Q (null) (Q) | |
Array of Package Type (strings) or Package Type (null) (Package Type) | |
Array of Severity (strings) or Severity (null) (Severity) | |
Array of License Category (strings) or License Category (null) (License Category) | |
Eol (boolean) or Eol (null) (Eol) | |
Outdated (boolean) or Outdated (null) (Outdated) | |
| sort | string (Sort) ^(name|project_count|severity|license)$ Default: "project_count" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| component_id required | string <uuid> (Component Id) |
| limit | integer (Limit) [ 1 .. 200 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
{- "items": [
- {
- "direct": true,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "scanned_at": "2019-08-24T14:15:22Z",
- "version": "string"
}
], - "limit": 0,
- "offset": 0,
- "total": 0
}| external_id required | string (External Id) <= 64 characters |
| limit | integer (Limit) [ 1 .. 200 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
{- "external_id": "string",
- "items": [
- {
- "component_name": "string",
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "purl": "string",
- "severity": "critical",
- "status": "string",
- "version": "string"
}
], - "limit": 0,
- "offset": 0,
- "severity": "critical",
- "total": 0
}Organization Id (string) or Organization Id (null) (Organization Id) | |
Team Id (string) or Team Id (null) (Team Id) | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| organization_id required | string <uuid> (Organization Id) |
{- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| organization_id required | string <uuid> (Organization Id) |
object (Category Overrides) | |
object (Compound Operator Strategy) | |
| enabled | boolean (Enabled) Default: true |
Array of objects (License Exceptions) | |
Array of objects (Malicious Exceptions) | |
Name (string) or Name (null) (Name) | |
| unknown_license_category | string (Unknown License Category) Default: "conditional" Enum: "allowed" "conditional" "forbidden" |
{- "category_overrides": {
- "property1": "allowed",
- "property2": "allowed"
}, - "compound_operator_strategy": {
- "property1": "most_restrictive",
- "property2": "most_restrictive"
}, - "enabled": true,
- "license_exceptions": [
- {
- "component_purl": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "reason": "string",
- "spdx_id": "string"
}
], - "malicious_exceptions": [
- {
- "component_purl": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "reason": "string"
}
], - "name": "string",
- "unknown_license_category": "allowed"
}{- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
{- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
object (Category Overrides) | |
object (Compound Operator Strategy) | |
| enabled | boolean (Enabled) Default: true |
Array of objects (License Exceptions) | |
Array of objects (Malicious Exceptions) | |
Name (string) or Name (null) (Name) | |
| unknown_license_category | string (Unknown License Category) Default: "conditional" Enum: "allowed" "conditional" "forbidden" |
{- "category_overrides": {
- "property1": "allowed",
- "property2": "allowed"
}, - "compound_operator_strategy": {
- "property1": "most_restrictive",
- "property2": "most_restrictive"
}, - "enabled": true,
- "license_exceptions": [
- {
- "component_purl": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "reason": "string",
- "spdx_id": "string"
}
], - "malicious_exceptions": [
- {
- "component_purl": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "reason": "string"
}
], - "name": "string",
- "unknown_license_category": "allowed"
}{- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| spdx_id required | string (Spdx Id) [ 1 .. 128 ] characters |
Component Purl (string) or Component Purl (null) (Component Purl) |
{- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
Component Purl (string) or Component Purl (null) (Component Purl) | |
Expires At (string) or Expires At (null) (Expires At) | |
| reason required | string (Reason) [ 1 .. 1000 ] characters |
| spdx_id required | string (Spdx Id) [ 1 .. 128 ] characters |
{- "component_purl": "string",
- "expires_at": "2019-08-24T14:15:22Z",
- "reason": "string",
- "spdx_id": "string"
}{- "category_overrides": {
- "property1": "string",
- "property2": "string"
}, - "compound_operator_strategy": {
- "property1": "string",
- "property2": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "enabled": true,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license_exceptions": [
- { }
], - "malicious_exceptions": [
- { }
], - "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "unknown_license_category": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| finding_id required | string <uuid> (Finding Id) |
{- "affected_components": [
- {
- "component_name": "string",
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "kind": "declared",
- "source_path": "string",
- "version": "string"
}
], - "affected_components_total": 0,
- "affected_components_truncated": false,
- "category": "allowed",
- "created_at": "2019-08-24T14:15:22Z",
- "finding_kind": "declared",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_deprecated_license_id": false,
- "is_fsf_libre": false,
- "is_osi_approved": false,
- "license_id": "38cf2dcf-77be-45c4-b03d-412af2743263",
- "name": "string",
- "ort_match": { },
- "osori": {
- "name": "string",
- "notification_required": true,
- "restrictions": [
- "string"
], - "source": "OSORI (olis.or.kr), ODC-By 1.0",
- "source_disclosure": "string"
}, - "reference_url": "string",
- "review_flag": "behavioral_use",
- "spdx_id": "string",
- "summary": "string",
- "summary_ko": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| project_id required | string <uuid> (Project Id) |
| limit | integer (Limit) [ 1 .. 500 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
Array of Category (strings) or Category (null) (Category) | |
Array of Kind (strings) or Kind (null) (Kind) | |
Search (string) or Search (null) (Search) | |
| sort | string (Sort) ^(category|name|spdx_id|affected_count)$ Default: "category" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
Review Flag (string) or Review Flag (null) (Review Flag) Filter to licenses carrying an AI review flag (Phase D). behavioral_use = RAIL/Llama/Gemma/Falcon community licenses; non_commercial = CC-BY-NC…. Omit to list all licenses. | |
Conflict (string) or Conflict (null) (Conflict) Filter to licenses carrying this outbound-conflict verdict (gap #27). Matches nothing when the project declares no outbound license, since nothing is assessed without one. Omit to list all. | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "conflict_summary": {
- "compatible": 0,
- "conditional": 0,
- "incompatible": 0,
- "unknown": 0
}, - "declared_license": "string",
- "distribution": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "items": [
- {
- "affected_count": 1,
- "category": "allowed",
- "conflict": {
- "dependency_class": "permissive",
- "verdict": "compatible",
- "why": "string"
}, - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_fsf_libre": false,
- "is_osi_approved": false,
- "kind": "declared",
- "license_id": "38cf2dcf-77be-45c4-b03d-412af2743263",
- "name": "string",
- "review_flag": "behavioral_use",
- "sample_finding_id": "e96d0bbe-3be6-488b-befa-536867c05879",
- "spdx_id": "string",
- "summary": "string",
- "summary_ko": "string"
}
], - "total": 0
}The same rows the list endpoint would return, without the paging.
Filters are applied by the list service itself rather than by a second query, so the file and the screen cannot disagree, and the cross-team check the list performs is the one this performs.
| project_id required | string <uuid> (Project Id) |
Array of Category (strings) or Category (null) (Category) | |
Array of Kind (strings) or Kind (null) (Kind) | |
Search (string) or Search (null) (Search) | |
| sort | string (Sort) ^(category|name|spdx_id|affected_count)$ Default: "category" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
Review Flag (string) or Review Flag (null) (Review Flag) | |
Conflict (string) or Conflict (null) (Conflict) | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| organization_id required | string <uuid> (Organization Id) |
| format required | string (Format) ^(text|markdown|html)$ |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| organization_id required | string <uuid> (Organization Id) |
| format required | string (Format) ^(text|markdown|html)$ |
{- "created_at": "2019-08-24T14:15:22Z",
- "footer": "string",
- "format": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "preface": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| organization_id required | string <uuid> (Organization Id) |
| format required | string (Format) ^(text|markdown|html)$ |
Footer (string) or Footer (null) (Footer) Plain text printed after the license list. Null clears it. | |
Preface (string) or Preface (null) (Preface) Plain text printed before the license list. Null clears it. |
{- "footer": "string",
- "preface": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "footer": "string",
- "format": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "preface": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| organization_id required | string <uuid> (Organization Id) |
{- "items": [
- {
- "channels": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "email_recipients": [
- "string"
], - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "kinds": [
- "string"
], - "min_severity": "string",
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "total": 0
}| organization_id required | string <uuid> (Organization Id) |
| channels | Array of strings (Channels) Channels this rule adds. Never removes one somebody enabled. |
| email_recipients | Array of strings <email> (Email Recipients) <= 50 items [ items <email > ] Addresses this rule adds. |
| is_active | boolean (Is Active) Default: true |
| kinds | Array of strings (Kinds) Notification kinds this rule covers. Empty means every kind. |
Min Severity (string) or Min Severity (null) (Min Severity) Matches this severity and everything above it. Omitted means severity is not part of the condition. A rule naming one does not fire for a notification that carries no severity at all. | |
| name required | string (Name) [ 1 .. 200 ] characters |
Project Id (string) or Project Id (null) (Project Id) One project. Omitted means every project in scope. |
{- "channels": [
- "string"
], - "email_recipients": [
- "user@example.com"
], - "is_active": true,
- "kinds": [
- "string"
], - "min_severity": "string",
- "name": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9"
}{- "channels": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "email_recipients": [
- "string"
], - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "kinds": [
- "string"
], - "min_severity": "string",
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
{- "items": [
- {
- "channels": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "email_recipients": [
- "string"
], - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "kinds": [
- "string"
], - "min_severity": "string",
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "total": 0
}| team_id required | string <uuid> (Team Id) |
| channels | Array of strings (Channels) Channels this rule adds. Never removes one somebody enabled. |
| email_recipients | Array of strings <email> (Email Recipients) <= 50 items [ items <email > ] Addresses this rule adds. |
| is_active | boolean (Is Active) Default: true |
| kinds | Array of strings (Kinds) Notification kinds this rule covers. Empty means every kind. |
Min Severity (string) or Min Severity (null) (Min Severity) Matches this severity and everything above it. Omitted means severity is not part of the condition. A rule naming one does not fire for a notification that carries no severity at all. | |
| name required | string (Name) [ 1 .. 200 ] characters |
Project Id (string) or Project Id (null) (Project Id) One project. Omitted means every project in scope. |
{- "channels": [
- "string"
], - "email_recipients": [
- "user@example.com"
], - "is_active": true,
- "kinds": [
- "string"
], - "min_severity": "string",
- "name": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9"
}{- "channels": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "email_recipients": [
- "string"
], - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "kinds": [
- "string"
], - "min_severity": "string",
- "name": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "updated_at": "2019-08-24T14:15:22Z"
}| unread_only | boolean (Unread Only) Default: false |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 20 |
{- "items": [
- {
- "body": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "scan_completed",
- "link": "string",
- "read_at": "2019-08-24T14:15:22Z",
- "target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9",
- "target_table": "string",
- "title": "string"
}
], - "page": 0,
- "page_size": 0,
- "total": 0,
- "unread_count": 0
}| notification_id required | string <uuid> (Notification Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
| component_id required | string <uuid> (Component Id) |
{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "justification": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "scope": "string",
- "status": "string"
}Rulings for one organization, readable by anybody inside it.
What each caller sees is not the same. The published reason goes to everybody, because it is what explains an inherited status on their own screen. The deliberation around it, and the names of the people involved, go only to callers who could have written them: a note an administrator made while deciding is not part of explaining the outcome.
| organization_id required | string <uuid> (Organization Id) |
Array of Status (strings) or Status (null) (Status) | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}
], - "page": 1,
- "page_size": 50,
- "total": 0
}| organization_id required | string <uuid> (Organization Id) |
| component_id required | string <uuid> (Component Id) |
| justification required | string (Justification) >= 10 characters Why this is being ruled on centrally. Required: this answer reaches every project that has not decided for itself, and it is the sentence people will ask about later. |
{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "justification": "stringstri"
}{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}| verdict_id required | string <uuid> (Verdict Id) |
Note (string) or Note (null) (Note) Optional reasoning, kept whichever way it went. | |
| status required | string (Status) under_review, approved or rejected. |
{- "note": "string",
- "status": "string"
}{- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}Team Id (string) or Team Id (null) (Team Id) | |
| include_archived | boolean (Include Archived) Default: false |
Q (string) or Q (null) (Q) | |
Business Unit (string) or Business Unit (null) (Business Unit) Narrow to one owning part of the organization. Omitted or blank leaves every project in, including the ones that have not set it. | |
Distribution Model (string) or Distribution Model (null) (Distribution Model) Narrow to one distribution model, or 'unset' for the projects that have not said how they ship. Omitted leaves every project in. | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 20 |
{- "items": [
- {
- "ai_usage_context": "internal",
- "archived_at": "2019-08-24T14:15:22Z",
- "business_unit": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_url": "string",
- "group_path": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "slug": "string"
}
], - "has_git_credential": false,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "last_scan_at": "2019-08-24T14:15:22Z",
- "latest_scan_id": "df070bcd-0cf7-4ee8-8a3b-eea17ac86447",
- "latest_scan_status": "queued",
- "license_category_summary": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "name": "string",
- "owner_contact": "string",
- "release_count": 0,
- "scan_count": 0,
- "severity_summary": {
- "critical": 0,
- "high": 0,
- "low": 0,
- "medium": 0
}, - "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}
], - "page": 0,
- "size": 0,
- "total": 0
}Ai Usage Context (string) or Ai Usage Context (null) (Ai Usage Context) How this project intends to use the AI models it carries. Narrows a model or dataset license to the conditions that bind that use ('internal', 'product', 'redistribute', 'outputs-only'). Omit to judge against the full terms, which is the conservative reading. | |
Business Unit (string) or Business Unit (null) (Business Unit) Which part of the organization owns this project. Free text: a division, a cost centre and a squad are the same slot to different organizations. Used to narrow the portfolio list. | |
Declared License (string) or Declared License (null) (Declared License) SPDX id or expression the project itself is distributed under ('Apache-2.0', 'MIT OR Apache-2.0'). Drives the outbound-license conflict verdicts on the Licenses tab. Omit or leave blank when the project does not declare one — no verdicts are produced, which is not the same as a clean result. | |
Default Branch (string) or Default Branch (null) (Default Branch) | |
Description (string) or Description (null) (Description) | |
Distribution Model (string) or Distribution Model (null) (Distribution Model) How this software reaches the people who use it: 'internal', 'saas', 'binary', 'source' or 'embedded'. Omit when it has not been decided, which is judged as though it ships every way. | |
Git Url (string) or Git Url (null) (Git Url) | |
| name required | string (Name) [ 1 .. 255 ] characters |
Owner Contact (string) or Owner Contact (null) (Owner Contact) Who to ask about this project. A name, a team alias or an address. | |
| slug required | string (Slug) [ 1 .. 64 ] characters |
| team_id required | string <uuid> (Team Id) |
| visibility | string (Visibility) Default: "team" Enum: "team" "organization" |
{- "ai_usage_context": "internal",
- "business_unit": "string",
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_url": "string",
- "name": "string",
- "owner_contact": "string",
- "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "visibility": "team"
}{- "ai_usage_context": "internal",
- "archived_at": "2019-08-24T14:15:22Z",
- "business_unit": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_url": "string",
- "group_path": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "slug": "string"
}
], - "has_git_credential": false,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "last_scan_at": "2019-08-24T14:15:22Z",
- "latest_scan_id": "df070bcd-0cf7-4ee8-8a3b-eea17ac86447",
- "latest_scan_status": "queued",
- "license_category_summary": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "name": "string",
- "owner_contact": "string",
- "release_count": 0,
- "scan_count": 0,
- "severity_summary": {
- "critical": 0,
- "high": 0,
- "low": 0,
- "medium": 0
}, - "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}The same rows the list endpoint would return, without the paging.
Filters and team-scoping are applied by list_projects itself rather
than by a second query, so the file and the screen cannot disagree.
Team Id (string) or Team Id (null) (Team Id) | |
| include_archived | boolean (Include Archived) Default: false |
Q (string) or Q (null) (Q) | |
Business Unit (string) or Business Unit (null) (Business Unit) | |
Distribution Model (string) or Distribution Model (null) (Distribution Model) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "ai_usage_context": "internal",
- "archived_at": "2019-08-24T14:15:22Z",
- "business_unit": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_url": "string",
- "group_path": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "slug": "string"
}
], - "has_git_credential": false,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "last_scan_at": "2019-08-24T14:15:22Z",
- "latest_scan_id": "df070bcd-0cf7-4ee8-8a3b-eea17ac86447",
- "latest_scan_status": "queued",
- "license_category_summary": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "name": "string",
- "owner_contact": "string",
- "release_count": 0,
- "scan_count": 0,
- "severity_summary": {
- "critical": 0,
- "high": 0,
- "low": 0,
- "medium": 0
}, - "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}| project_id required | string <uuid> (Project Id) |
Ai Usage Context (string) or Ai Usage Context (null) (Ai Usage Context) How this project intends to use its AI models ('internal', 'product', 'redistribute', 'outputs-only'). Send an empty string to clear it and judge against the full terms; omit the field to leave it unchanged. | |
Business Unit (string) or Business Unit (null) (Business Unit) Which part of the organization owns this project. Send an empty string to clear it; omit the field to leave it unchanged. | |
| clear_git_credential | boolean (Clear Git Credential) Default: false Set true to remove a stored git credential (column → NULL). Cannot be combined with a non-empty |
Declared License (string) or Declared License (null) (Declared License) SPDX id or expression the project is distributed under. Send an empty string to remove an existing declaration; omit the field to leave it unchanged. | |
Default Branch (string) or Default Branch (null) (Default Branch) | |
Description (string) or Description (null) (Description) | |
Distribution Model (string) or Distribution Model (null) (Distribution Model) How this software reaches its users ('internal', 'saas', 'binary', 'source', 'embedded'). Send an empty string to clear it and judge as though it ships every way; omit to leave it unchanged. | |
Git Credential (string) or Git Credential (null) (Git Credential) Write-only plaintext git credential (PAT / deploy token) for cloning a private repo. Encrypted at rest; NEVER returned in any response. Provide a non-empty value to set/rotate it. Omit to leave it unchanged. Use | |
Git Url (string) or Git Url (null) (Git Url) | |
Name (string) or Name (null) (Name) | |
Owner Contact (string) or Owner Contact (null) (Owner Contact) Who to ask about this project. Send an empty string to clear it; omit the field to leave it unchanged. | |
Visibility (string) or Visibility (null) (Visibility) |
{- "ai_usage_context": "internal",
- "business_unit": "string",
- "clear_git_credential": false,
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_credential": "string",
- "git_url": "string",
- "name": "string",
- "owner_contact": "string",
- "visibility": "team"
}{- "ai_usage_context": "internal",
- "archived_at": "2019-08-24T14:15:22Z",
- "business_unit": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_url": "string",
- "group_path": [
- {
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "name": "string",
- "slug": "string"
}
], - "has_git_credential": false,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "last_scan_at": "2019-08-24T14:15:22Z",
- "latest_scan_id": "df070bcd-0cf7-4ee8-8a3b-eea17ac86447",
- "latest_scan_status": "queued",
- "license_category_summary": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "name": "string",
- "owner_contact": "string",
- "release_count": 0,
- "scan_count": 0,
- "severity_summary": {
- "critical": 0,
- "high": 0,
- "low": 0,
- "medium": 0
}, - "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "team_name": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}Who may be named as the owner of a finding or an obligation here.
Addressed by project rather than by team because that is what a caller holds: the screen is a project's finding list, and asking it for a team id would mean handing out team ids to look work up by. The team is derived here, and access is the project's own rule.
developer for the same reason the assignment PATCH is: a caller who may
perform an assignment has to be able to compose one, and a list gated
higher would leave the write reachable only by somebody who already knew
the id.
The set is exactly what services.assignee will accept, because both go
through one predicate rather than two copies of three conditions.
Deriving the team from the project used to be safe because reaching a
project meant being on its team, full stop. A later change made
get_project above cascade-aware (it now runs its team gate through
core.authz.assert_team_access / can_access_group, same as every
other single-resource surface), so that premise no longer holds
unconditionally: with the cascade flag on, an actor can reach
get_project through an ANCESTOR group's direct membership, without
being a direct member of project.team_id itself.
services.assignee (the picker below, and the write-time eligibility
check the assignment PATCH uses) already anticipated this: PR 2-C widened
it to the project's team's ancestors when
:func:core.config.group_cascade_enabled is on, specifically so this
route would not need a second, coordinated change once get_project
itself was cascaded. It was. So this route's set stays exactly what
services.assignee accepts, in both flag states, with no change needed
here.
Organization-wide visibility (a different widening, not the group
cascade) would still end the "reaching a project means being on its
team" premise for get_project itself. Somebody on another team could
then read the project, and this route would hand them its members,
which is the enumeration the tests here refuse. Whoever enables it has
to decide what this endpoint does: most likely keep it on team
membership rather than on project access, since being allowed to read a
project's findings is not the same as being allowed to list the people
on it.
core.authz.team_scope_filter carries a pointer back here, because
that is the file the change lands in.
| project_id required | string <uuid> (Project Id) |
{- "members": [
- {
- "full_name": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "total": 0
}| project_id required | string <uuid> (Project Id) |
| limit | integer (Limit) [ 1 .. 500 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
Search (string) or Search (null) (Search) | |
Array of Severity (strings) or Severity (null) (Severity) | |
Array of License Category (strings) or License Category (null) (License Category) | |
Direct (boolean) or Direct (null) (Direct) W2 #31 — Direct/Transitive toggle. | |
Array of Dependency Scope (strings) or Dependency Scope (null) (Dependency Scope) W2 #31 — commercial-SCA-style 'Usage' facet. Repeatable; accepted values: | |
Eol (boolean) or Eol (null) (Eol) Phase M — end-of-life facet. | |
Outdated (boolean) or Outdated (null) (Outdated) Version-currency facet (sibling of the EOL filter). | |
Malicious (boolean) or Malicious (null) (Malicious) Known-malicious facet (#26). | |
| sort | string (Sort) ^(name|severity|license)$ Default: "name" |
| order | string (Order) ^(asc|desc)$ Default: "asc" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "items": [
- {
- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "currency_latest": "string",
- "currency_state": "current",
- "dependency_scope": "required",
- "depth": 0,
- "direct": false,
- "eol_date": "2019-08-24",
- "eol_state": "eol",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license": "string",
- "license_category": "forbidden",
- "malicious_id": "string",
- "malicious_source": "string",
- "malicious_state": "flagged",
- "name": "string",
- "purl": "string",
- "severity_max": "critical",
- "version": "string",
- "vulnerability_count": 0
}
], - "limit": 0,
- "offset": 0,
- "total": 0
}The same rows the list endpoint would return, without the paging.
Filters are applied by the list service itself rather than by a second query, so the file and the screen cannot disagree, and the cross-team check the list performs is the one this performs.
sort/order are still accepted and validated but no longer decide
the exported rows' order (#463): the export walks a fixed key (the
component_version id) instead, so a bill of materials that reaches real
depth does not pay for OFFSET's cost growing with it.
| project_id required | string <uuid> (Project Id) |
Search (string) or Search (null) (Search) | |
Array of Severity (strings) or Severity (null) (Severity) | |
Array of License Category (strings) or License Category (null) (License Category) | |
Direct (boolean) or Direct (null) (Direct) | |
Array of Dependency Scope (strings) or Dependency Scope (null) (Dependency Scope) | |
Eol (boolean) or Eol (null) (Eol) | |
Outdated (boolean) or Outdated (null) (Outdated) | |
Malicious (boolean) or Malicious (null) (Malicious) | |
| sort | string (Sort) ^(name|severity|license)$ Default: "name" |
| order | string (Order) ^(asc|desc)$ Default: "asc" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "edge_count": 2,
- "edges": [
- {
- "source": "0a4d1f2e-1111-4a2b-9c3d-000000000001",
- "target": "0a4d1f2e-1111-4a2b-9c3d-000000000002"
}, - {
- "source": "0a4d1f2e-1111-4a2b-9c3d-000000000001",
- "target": "0a4d1f2e-1111-4a2b-9c3d-000000000003"
}
], - "node_cap": 5000,
- "node_count": 3,
- "nodes": [
- {
- "depth": 1,
- "direct": true,
- "id": "0a4d1f2e-1111-4a2b-9c3d-000000000001",
- "max_severity": "none",
- "name": "app",
- "purl": "pkg:npm/app@1.0.0",
- "version": "1.0.0",
- "vulnerability_count": 0
}, - {
- "depth": 2,
- "direct": false,
- "id": "0a4d1f2e-1111-4a2b-9c3d-000000000002",
- "max_severity": "high",
- "name": "lodash",
- "purl": "pkg:npm/lodash@4.17.20",
- "version": "4.17.20",
- "vulnerability_count": 1
}, - {
- "depth": 2,
- "direct": false,
- "id": "0a4d1f2e-1111-4a2b-9c3d-000000000003",
- "max_severity": "critical",
- "name": "log4j-core",
- "namespace": "org.apache.logging.log4j",
- "purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
- "version": "2.14.1",
- "vulnerability_count": 1
}
], - "scan_id": "3c15c82f-c409-4f5f-b7d9-92bca8cc1f7f",
- "truncated": false
}| project_id required | string <uuid> (Project Id) |
| base required | string <uuid> (Base) Base snapshot scan id (typically the OLDER release, e.g. v0.1). Must belong to this project and be succeeded, else 404 (existence-hide). |
| target required | string <uuid> (Target) Target snapshot scan id (typically the NEWER release, e.g. v0.2). Must belong to this project and be succeeded, else 404. |
{- "base": {
- "created_at": "2026-05-20T10:00:00Z",
- "release": "v0.1",
- "scan_id": "3c15c82f-c409-4f5f-b7d9-92bca8cc1f7f"
}, - "components": {
- "added": [
- {
- "name": "log4j-core",
- "namespace": "org.apache.logging.log4j",
- "purl": "pkg:maven/org.apache.logging.log4j/log4j-core@2.14.1",
- "version": "2.14.1"
}
], - "changed": [
- {
- "base_version": "4.17.20",
- "name": "lodash",
- "purl": "pkg:npm/lodash",
- "target_version": "4.17.21"
}
], - "removed": [ ]
}, - "licenses": {
- "category_delta": {
- "conditional": {
- "base": 0,
- "target": 2
}, - "permissive": {
- "base": 0,
- "target": 80
}, - "prohibited": {
- "base": 0,
- "target": 1
}, - "unknown": {
- "base": 0,
- "target": 5
}
}
}, - "summary": {
- "component_count": {
- "base": 0,
- "target": 88
}, - "gate": {
- "base": "pass",
- "target": "fail"
}, - "risk_score": {
- "base": 0,
- "target": 92.9
}, - "severity": {
- "critical": {
- "base": 0,
- "target": 10
}, - "high": {
- "base": 0,
- "target": 8
}, - "low": {
- "base": 0,
- "target": 5
}, - "medium": {
- "base": 0,
- "target": 20
}
}
}, - "target": {
- "created_at": "2026-05-22T10:00:00Z",
- "scan_id": "50b3d477-2211-47a3-947b-69022dabb2b3"
}, - "truncated": false,
- "vulnerabilities": {
- "introduced": [
- {
- "component_name": "log4j-core",
- "component_version": "2.14.1",
- "cve_id": "CVE-2021-44228",
- "severity": "critical"
}
], - "resolved": [ ]
}
}The governance band's payload — five signals the page already owns.
Every number is produced by the service that owns it elsewhere in the
product (risk score, evaluate_gate, the KEV bucket, the approvals
count), so the band cannot disagree with the tab below it. See
services.project_governance_service.
Same access contract as /overview: a project on a team the caller does
not belong to is a 403 and a missing one a 404, both as problem+json.
| project_id required | string <uuid> (Project Id) |
{- "gate": {
- "critical_cve_count": 0,
- "epss_gate_count": 0,
- "forbidden_license_count": 0,
- "malicious_component_count": 0,
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "status": "string"
}, - "kev_sla": {
- "due_soon": 0,
- "overdue": 0
}, - "pending_approvals": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "risk_score": 100,
- "scanned": true,
- "trend": [
- {
- "critical": 0,
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "scanned_at": "2019-08-24T14:15:22Z"
}
]
}| project_id required | string <uuid> (Project Id) |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "component_outcome": "string",
- "current_user_role": "super_admin",
- "eol_count": 0,
- "has_git_credential": false,
- "last_scan_at": "2019-08-24T14:15:22Z",
- "last_succeeded_scan_at": "2019-08-24T14:15:22Z",
- "license_distribution": {
- "property1": 0,
- "property2": 0
}, - "license_score": 100,
- "malicious_count": 0,
- "outdated_count": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "recent_scans": [
- {
- "completed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "progress_percent": 0,
- "ref": "string",
- "release": "string",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "string"
}
], - "risk_score": 100,
- "security_score": 100,
- "severity_distribution": {
- "property1": 0,
- "property2": 0
}, - "total_components": 0
}| project_id required | string <uuid> (Project Id) |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 20 |
Release (string) or Release (null) (Release) Optional version label filter (e.g. '4.0'), matched exactly against the scan's | |
Ref (string) or Ref (null) (Ref) Optional branch filter. Accepts a bare branch ( |
{- "items": [
- {
- "component_count": 42,
- "created_at": "2026-05-22T10:00:00Z",
- "gate_status": "fail",
- "ref": "v1.2.3",
- "release": "v1.2.3",
- "risk_score": 92.9,
- "scan_id": "7822b62d-9156-423d-9df6-5e51f546fbe8",
- "severity_summary": {
- "critical": 10,
- "high": 4,
- "low": 1,
- "medium": 2
}
}
], - "page": 1,
- "size": 20,
- "total": 1
}| project_id required | string <uuid> (Project Id) |
| kind | string (Kind) Default: "source" Enum: "source" "container" "sbom" |
object (Metadata) |
{- "kind": "source",
- "metadata": { }
}{- "celery_task_id": "string",
- "completed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "current_step": "string",
- "error_message": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "source",
- "metadata": { },
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "ref": "string",
- "release": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "superseded_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| project_id required | string <uuid> (Project Id) |
| upload required | string <application/octet-stream> (Upload) A .zip archive of the project source tree. |
{- "archive_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}Configured or not, and for which provider. Never the secret.
Split from the issue route so the question a screen asks has an answer that carries no credential bytes. There is no route that returns the secret after issuance, and this is the one somebody would be tempted to add it to.
| project_id required | string <uuid> (Project Id) |
{- "configured": true,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "provider": "github"
}Turn the webhook on, and hand back the secret once.
This replaced an operator running an UPDATE by hand. The column holds ciphertext now and SQL cannot produce it, so the procedure had to move into the product; having moved, it gets what the SQL never had, which is a permission check, an audit row, and one path that sets both fields.
team_admin rather than developer: this decides whether a repository
can make this deployment start scans, and it is the same level that edits
the project's other settings.
Calling it again replaces the secret. The response says so in
replaced_existing, because the old value stops being accepted the
moment this returns and the deliveries that were working will fail until
the new one reaches the SCM. Somebody who meant to read the current value
and found there is no such route would otherwise learn this by breaking
their own integration.
| project_id required | string <uuid> (Project Id) |
| provider required | string (Provider) Enum: "github" "gitlab" Which SCM will send the deliveries. It decides the header schema the gateway applies: GitHub signs the body and sends X-Hub-Signature-256, GitLab sends the secret itself as X-Gitlab-Token. A project configured for one and receiving from the other has every delivery refused. |
{- "provider": "github"
}{- "issued_at": "2019-08-24T14:15:22Z",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "provider": "github",
- "replaced_existing": true,
- "secret": "string"
}Register a set of repositories as projects.
Rows are independent: one the caller may not create, or one whose slug the team already uses, is reported and the rest still land. Onboarding an organization means creating a project per repository, and failing the whole request over a single repository would make that unusable.
Status is 201 when every row succeeded and 207 when any did not, so a script can branch on the status line alone. A row whose project already exists counts as success: re-running to finish an interrupted onboarding is the normal path, and reporting that as failure would make every re-run look broken.
required | Array of objects (Projects) [ 1 .. 200 ] items Projects to create, at most 200. Each entry is the same body | ||||||||||||||||||||||||
Array ([ 1 .. 200 ] items)
| |||||||||||||||||||||||||
{- "projects": [
- {
- "ai_usage_context": "internal",
- "business_unit": "string",
- "declared_license": "string",
- "default_branch": "string",
- "description": "string",
- "distribution_model": "internal",
- "git_url": "string",
- "name": "string",
- "owner_contact": "string",
- "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "visibility": "team"
}
]
}{- "all_succeeded": true,
- "already_existed": 0,
- "created": 0,
- "failed": 0,
- "failed_by_status": {
- "property1": 0,
- "property2": 0
}, - "rows": [
- {
- "detail": "string",
- "index": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "retry_after_seconds": 0,
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "status": "created"
}
], - "total": 0
}| project_id required | string <uuid> (Project Id) |
| limit | integer (Limit) [ 1 .. 500 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
Array of Category (strings) or Category (null) (Category) Filter rows by license category. Repeat the parameter to OR-join multiple values (e.g. ?category=forbidden&category=conditional). | |
Array of Kind (strings) or Kind (null) (Kind) Filter rows to licenses that carry at least one obligation of the given kind. Repeat to OR-join. | |
Search (string) or Search (null) (Search) Substring match against SPDX id and license name. LIKE metacharacters are escaped server-side. | |
Has Obligations (boolean) or Has Obligations (null) (Has Obligations) When true, return only licenses that carry at least one obligation row. When false, return only licenses with NONE. Ignored when | |
| sort | string (Sort) ^(category|license_name|spdx_id|affected_coun... Default: "category" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
Conflict (string) or Conflict (null) (Conflict) Filter to licenses carrying this outbound-conflict verdict (gap #27). Matches nothing when the project declares no outbound license, since nothing is assessed without one. Omit to list all. | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "conflict_summary": {
- "compatible": 0,
- "conditional": 0,
- "incompatible": 0,
- "unknown": 0
}, - "declared_license": "string",
- "distribution": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "generated_at": "2019-08-24T14:15:22Z",
- "items": [
- {
- "affected_component_count": 0,
- "affected_components": [
- {
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "name": "string",
- "purl": "string",
- "version": "string"
}
], - "category": "allowed",
- "category_override_source": "string",
- "category_source": "static",
- "conflict": {
- "dependency_class": "permissive",
- "verdict": "compatible",
- "why": "string"
}, - "kind": "declared",
- "license_finding_id": "2420a37e-d48a-4bfc-bb16-348aef968254",
- "license_id": "38cf2dcf-77be-45c4-b03d-412af2743263",
- "license_name": "string",
- "notice_required": false,
- "obligations": [
- {
- "kind": "string",
- "obligation_id": "0769bb4d-4595-4f74-b251-51ff3f5695a5",
- "summary": "string",
- "summary_ko": "string"
}
], - "spdx_id": "string"
}
], - "limit": 1,
- "offset": 0,
- "total": 0
}| project_id required | string <uuid> (Project Id) |
Ref (string) or Ref (null) (Ref) Optional branch anchor: evaluate against the newest succeeded scan of this normalized git ref ( | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "component_outcome": "string",
- "critical_cve_count": 0,
- "eol_gate_count": 0,
- "eol_gate_enabled": false,
- "eol_on_missing_data": "allow",
- "eol_outcome": "not_configured",
- "epss_gate_count": 0,
- "epss_on_missing_data": "allow",
- "epss_outcome": "not_configured",
- "epss_threshold": 1,
- "evaluated_at": "2019-08-24T14:15:22Z",
- "forbidden_license_count": 0,
- "gate": "pass",
- "kev_gate_count": 0,
- "kev_gate_enabled": false,
- "kev_on_missing_data": "allow",
- "kev_outcome": "not_configured",
- "malicious_component_count": 0,
- "malicious_gate_enforced": true,
- "malicious_scan_assessed": false,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "reachable_critical_cve_count": 0,
- "reachable_gate_enforced": false,
- "reason": "string",
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af"
}Emit the scan's open findings in the format code-scanning tools ingest.
Access control, snapshot anchoring and ref normalisation are the gate endpoint's, deliberately: this is the same data in another representation, so a caller who may read the verdict may read this, and a caller who may not gets the same existence-hiding 404.
A project with no succeeded scan returns an empty-but-valid document rather than a 404. That is what a CI job must be able to upload: an empty run is how code scanning learns that previously-reported alerts are gone, and a 404 here would either fail the job or leave stale alerts standing forever.
| project_id required | string <uuid> (Project Id) |
Ref (string) or Ref (null) (Ref) Optional branch anchor, resolved exactly as for the gate verdict: a CI job should pass its own ref so the document it uploads describes its own branch rather than the project's main line. | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| scan_id required | string <uuid> (Scan Id) |
| dry_run | boolean (Dry Run) Default: false When |
| pr_number required | integer (Pr Number) [ 1 .. 10000000 ] The pull request number on GitHub, or the merge request IID on GitLab. The IID is the per-project number in the MR's URL, not the instance-wide |
| provider | string (Provider) Default: "github" Enum: "github" "gitlab" Which forge to comment on. Defaults to |
| repo_full_name required | string (Repo Full Name) [ 3 .. 140 ] characters The project's full path. The name says |
{- "dry_run": false,
- "pr_number": 1,
- "provider": "github",
- "repo_full_name": "string"
}{- "body_preview": "string",
- "comment_id": 0,
- "comment_url": "string",
- "gate": "pass",
- "provider": "github",
- "provider_assumed": false,
- "status": "posted"
}| project_id required | string <uuid> (Project Id) |
| format | string (Format) ^(text|markdown|html)$ Default: "text" Output format. |
| download | boolean (Download) Default: false When true, set |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
null| project_id required | string <uuid> (Project Id) |
{- "items": [
- {
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "completed_at": "2019-08-24T14:15:22Z",
- "completed_by_user_id": "46d01d21-f637-42aa-839a-6d4daf42c3a4",
- "created_at": "2019-08-24T14:15:22Z",
- "due_on": "2019-08-24",
- "evidence_note": "string",
- "evidence_url": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "obligation_id": "0769bb4d-4595-4f74-b251-51ff3f5695a5",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}
], - "total": 0
}| project_id required | string <uuid> (Project Id) |
| limit | integer (Limit) [ 1 .. 500 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
Array of Kind (strings) or Kind (null) (Kind) | |
Array of Category (strings) or Category (null) (Category) | |
Search (string) or Search (null) (Search) | |
| sort | string (Sort) ^(category|license_name|kind|affected_count)$... Default: "category" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "distribution": {
- "property1": 0,
- "property2": 0
}, - "items": [
- {
- "affected_count": 0,
- "fulfilment": {
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "completed_at": "2019-08-24T14:15:22Z",
- "completed_by_user_id": "46d01d21-f637-42aa-839a-6d4daf42c3a4",
- "due_on": "2019-08-24",
- "evidence_note": "string",
- "evidence_url": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}, - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "license_category": "allowed",
- "license_id": "38cf2dcf-77be-45c4-b03d-412af2743263",
- "license_name": "string",
- "license_spdx_id": "string",
- "link": "string",
- "text": "string",
- "text_ko": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "total": 0
}| project_id required | string <uuid> (Project Id) |
| obligation_id required | string <uuid> (Obligation Id) |
{- "affected_components": [
- {
- "component_name": "string",
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "version": "string"
}
], - "affected_components_total": 0,
- "affected_components_truncated": false,
- "created_at": "2019-08-24T14:15:22Z",
- "fulfilment": {
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "completed_at": "2019-08-24T14:15:22Z",
- "completed_by_user_id": "46d01d21-f637-42aa-839a-6d4daf42c3a4",
- "due_on": "2019-08-24",
- "evidence_note": "string",
- "evidence_url": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}, - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "license_category": "allowed",
- "license_id": "38cf2dcf-77be-45c4-b03d-412af2743263",
- "license_name": "string",
- "license_reference_url": "string",
- "license_spdx_id": "string",
- "link": "string",
- "text": "string",
- "text_ko": "string",
- "text_truncated": false,
- "updated_at": "2019-08-24T14:15:22Z"
}| project_id required | string <uuid> (Project Id) |
| obligation_id required | string <uuid> (Obligation Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}Create or replace the record. One call either way.
The caller is saying what the state is now; making them find out first whether a row exists would be a round trip that answers a question about our schema rather than about their work.
| project_id required | string <uuid> (Project Id) |
| obligation_id required | string <uuid> (Obligation Id) |
Assignee User Id (string) or Assignee User Id (null) (Assignee User Id) Who is doing it. Must be an active person on the project's team. | |
Due On (string) or Due On (null) (Due On) When it is needed by. | |
Evidence Note (string) or Evidence Note (null) (Evidence Note) What was done, in the words of whoever did it. | |
Evidence Url (string) or Evidence Url (null) (Evidence Url) Where to look: a release page, a file in the repository, a ticket. A link rather than an upload, so the portal does not become a second place the evidence can be wrong. | |
| status required | string (Status) One of: not_started, in_progress, done, not_applicable. 'not_applicable' is a real answer rather than a way of hiding one: an obligation that binds a shipped binary need not bind an internal service, and saying so is more useful than an untouched row, which reads as nobody having looked. |
{- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "due_on": "2019-08-24",
- "evidence_note": "string",
- "evidence_url": "string",
- "status": "string"
}{- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "completed_at": "2019-08-24T14:15:22Z",
- "completed_by_user_id": "46d01d21-f637-42aa-839a-6d4daf42c3a4",
- "created_at": "2019-08-24T14:15:22Z",
- "due_on": "2019-08-24",
- "evidence_note": "string",
- "evidence_url": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "obligation_id": "0769bb4d-4595-4f74-b251-51ff3f5695a5",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "status": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "version": 0
}| project_id required | string <uuid> (Project Id) |
Manifest (string) or Manifest (null) (Manifest) Raw package.json text to edit. When omitted, the endpoint reads the manifest from the latest preserved scan source (best-effort). | |
Any of string (Manifest) Raw package.json text to edit. When omitted, the endpoint reads the manifest from the latest preserved scan source (best-effort). | |
{- "manifest": "{\n \"name\": \"demo\",\n \"dependencies\": {\n \"lodash\": \"^4.17.20\"\n }\n}\n"
}{- "changed": true,
- "changes": [
- {
- "after": "^4.17.21",
- "before": "^4.17.20",
- "changed": true,
- "package": "lodash",
- "section": "dependencies"
}
], - "ecosystem": "npm",
- "edited_manifest": "{\n \"name\": \"demo\",\n \"dependencies\": {\n \"lodash\": \"^4.17.21\"\n }\n}\n",
- "manifest_found": true,
- "manifest_source": "preserved_source",
- "notes": [ ],
- "project_id": "5b8f1c2e-0c2a-4a1e-9c3d-9c2b1a0f7e11",
- "recommendations": [
- {
- "current_version": "4.17.20",
- "package": "lodash",
- "recommended_version": "4.17.21"
}
], - "scan_id": "7a1d2c3b-4e5f-6a7b-8c9d-0e1f2a3b4c5d",
- "warnings": [
- {
- "code": "lockfile_regeneration_required",
- "detail": "run `npm install` to regenerate package-lock.json"
}
]
}Open (or return the existing) automated npm remediation PR.
team_admin RBAC + opt-in enforcement live in the service. Returns 201 for a freshly opened PR, 200 for an idempotent hit on an existing open PR, and 204 when there is nothing to remediate.
| project_id required | string <uuid> (Project Id) |
Manifest (string) or Manifest (null) (Manifest) Raw package.json text to edit. When omitted, the service reads the manifest from the latest preserved scan source (best-effort). | |
Any of string (Manifest) Raw package.json text to edit. When omitted, the service reads the manifest from the latest preserved scan source (best-effort). | |
{- "manifest": "{\n \"name\": \"demo\",\n \"dependencies\": {\n \"lodash\": \"^4.17.20\"\n }\n}\n"
}{- "base_branch": "main",
- "created_at": "2026-05-25T12:00:00Z",
- "ecosystem": "npm",
- "head_branch": "trustedoss/remediation-1a2b3c4d",
- "id": "9c2b1a0f-7e11-4a1e-9c3d-5b8f1c2e0c2a",
- "package_changes": [
- {
- "from": "4.17.20",
- "package": "lodash",
- "to": "4.17.21"
}
], - "pr_number": 42,
- "project_id": "5b8f1c2e-0c2a-4a1e-9c3d-9c2b1a0f7e11",
- "repository_full_name": "acme/widget",
- "status": "open",
- "updated_at": "2026-05-25T12:00:01Z"
}| project_id required | string <uuid> (Project Id) |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 |
{- "items": [
- {
- "base_branch": "main",
- "created_at": "2026-05-25T12:00:00Z",
- "ecosystem": "npm",
- "head_branch": "trustedoss/remediation-1a2b3c4d",
- "id": "9c2b1a0f-7e11-4a1e-9c3d-5b8f1c2e0c2a",
- "package_changes": [
- {
- "from": "4.17.20",
- "package": "lodash",
- "to": "4.17.21"
}
], - "pr_number": 42,
- "project_id": "5b8f1c2e-0c2a-4a1e-9c3d-9c2b1a0f7e11",
- "repository_full_name": "acme/widget",
- "status": "open",
- "updated_at": "2026-05-25T12:00:01Z"
}
], - "total": 1
}| project_id required | string <uuid> (Project Id) |
Array of Type (strings) or Type (null) (Type) Optional filter — one or more report_type values to include. Repeat the parameter ( | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 1-based page number. |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 Rows per page (1..200, default 50). |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "format": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "report_type": "notice",
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "size_bytes": 0,
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "user": {
- "email": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
}
], - "page": 1,
- "page_size": 1,
- "total": 0
}| project_id required | string <uuid> (Project Id) |
Array of Vulnerability Columns (strings) or Vulnerability Columns (null) (Vulnerability Columns) Subset of ['cve', 'cvss', 'summary', 'status'] to render. Overrides the organization's report formatting default for this request only. | |
Array of Component Columns (strings) or Component Columns (null) (Component Columns) Subset of ['name', 'version', 'license', 'severity', 'vulns'] to render. Overrides the organization's report formatting default for this request only. |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
| format | string (Format) Default: "cyclonedx-json" Enum: "cyclonedx-json" "cyclonedx-xml" "spdx-json" "spdx-tv" SBOM output format. |
Profile (string) or Profile (null) (Profile) Optional policy profile (C3). Applies the project's effective license policy: 'policy-annotated' flags each violating component in place (CycloneDX properties / SPDX annotations); 'policy-filtered' drops forbidden components (and their VEX entries), recording the excluded count on the document. Omit for the canonical, cosign-signable default export. Profile exports are NOT signed. | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
Ref (string) or Ref (null) (Ref) Optional git ref this SBOM was produced from (e.g. refs/heads/main, a tag, or a bare branch name). Normalized into a retention key. | |
Release (string) or Release (null) (Release) Optional release/version label for the resulting snapshot. | |
| sbom required | string <application/octet-stream> (Sbom) A CycloneDX-JSON (.json / .cdx.json) or SPDX (.spdx / .spdx.json / .tag) SBOM document. Trivy auto-detects the format for CVE matching; SPDX is mapped to CycloneDX for component persistence. |
{- "celery_task_id": "string",
- "completed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "current_step": "string",
- "error_message": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "source",
- "metadata": { },
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "ref": "string",
- "release": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "superseded_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
| scan_id required | string <uuid> (Scan Id) |
{- "ai_assessment": {
- "condition_labels": {
- "property1": {
- "property1": "string",
- "property2": "string"
}, - "property2": {
- "property1": "string",
- "property2": "string"
}
}, - "datasets": [
- {
- "bom_ref": "string",
- "dataset_refs": [
- "string"
], - "dataset_verdict": "ok",
- "name": "string",
- "reasons": [
- {
- "conditions": [
- "string"
], - "license": "string",
- "source_url": "string",
- "summary": "string",
- "summary_ko": "string",
- "term_key": "string",
- "term_name": "string",
- "verdict": "ok"
}
], - "verdict": "ok"
}
], - "disclaimer": "string",
- "disclaimer_ko": "string",
- "models": [
- {
- "bom_ref": "string",
- "dataset_refs": [
- "string"
], - "dataset_verdict": "ok",
- "name": "string",
- "reasons": [
- {
- "conditions": [
- "string"
], - "license": "string",
- "source_url": "string",
- "summary": "string",
- "summary_ko": "string",
- "term_key": "string",
- "term_name": "string",
- "verdict": "ok"
}
], - "verdict": "ok"
}
], - "scenario": "internal",
- "verdict": "ok"
}, - "checks": [
- {
- "cluster": "string",
- "detail": "string",
- "evidence": [
- "string"
], - "guidance": {
- "docUrl": "string",
- "snippet": "string"
}, - "id": "string",
- "label": "string",
- "missing": [
- "string"
], - "regulations": [
- {
- "basis": "string",
- "framework": "string",
- "ref": "string",
- "short": "string",
- "short_ko": "string"
}
], - "required": true,
- "review": {
- "how": "string",
- "how_ko": "string"
}, - "role": "string",
- "source": "string",
- "status": "pass"
}
], - "component_count": 0,
- "created_at": "2019-08-24T14:15:22Z",
- "hash_coverage_pct": 0,
- "license_coverage_pct": 0,
- "n_fail": 0,
- "n_warn": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "purl_coverage_pct": 0,
- "regulatory_crosswalk": {
- "disclaimer": "string",
- "disclaimer_ko": "string",
- "frameworks": [
- {
- "elements": [
- {
- "detail": "string",
- "id": "string",
- "label": "string",
- "refs": [
- "string"
], - "source": "string",
- "status": "pass"
}
], - "gap": 0,
- "id": "string",
- "present": 0,
- "review": 0,
- "short": "string",
- "short_ko": "string",
- "source": "string",
- "title": "string",
- "title_ko": "string",
- "total": 0
}
]
}, - "result": "pass",
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "source_format": "cyclonedx"
}| project_id required | string <uuid> (Project Id) |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 20 |
Ref (string) or Ref (null) (Ref) Optional branch filter. Accepts a bare branch ( |
{- "items": [
- {
- "celery_task_id": "string",
- "completed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "current_step": "string",
- "error_message": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "source",
- "metadata": { },
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "ref": "string",
- "release": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "superseded_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "size": 0,
- "total": 0
}Status (string) or Status (null) (Status) Filter by scan status. | |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 20 |
{- "items": [
- {
- "celery_task_id": "string",
- "completed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "current_step": "string",
- "error_message": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "source",
- "metadata": { },
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "ref": "string",
- "release": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "superseded_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "page": 0,
- "size": 0,
- "total": 0
}Hard-delete a terminal scan and (via cascade) its findings / components.
DT-style retention reclaims most stale scans automatically; this is the
manual escape hatch. Auth: any team member (developer+). The owning-team
check lives in the service (delete_scan), which existence-hides other
teams' scans as 404. Active scans (queued/running) return 409 — cancel
first. A release-labelled scan returns 409 unless force=true.
| scan_id required | string <uuid> (Scan Id) |
| force | boolean (Force) Default: false Delete even when the scan carries an explicit metadata.release label. Release-labelled snapshots are immutable by default. |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| scan_id required | string <uuid> (Scan Id) |
{- "celery_task_id": "string",
- "completed_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "current_step": "string",
- "error_message": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "source",
- "metadata": { },
- "progress_percent": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "ref": "string",
- "release": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "started_at": "2019-08-24T14:15:22Z",
- "status": "queued",
- "superseded_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Cancel one of the caller's own team's scans.
PR-A1 (scan stability). Auth: any authenticated team member
(developer or higher). The owning-team check lives in the service
(cancel_scan_for_actor) which existence-hides other teams' scans as
404 — so a developer cannot probe scan ids belonging to other teams.
Admin force-cancel (POST /v1/admin/scans/{id}/cancel) remains separate
and cross-team; the two share the same revoke + status-mutation core.
| scan_id required | string <uuid> (Scan Id) |
nullStream the per-scan scan.log written by tasks._progress.publish_log.
Authorization: same gate as GET /v1/scans/{scan_id} — reuses
services.scan_service.get_scan so team-membership / super-admin rules
stay in lock-step with the metadata endpoint. A non-member sees the same
404 as a non-existent scan id (existence-hide) so a developer cannot probe
scan ids belonging to other teams via this endpoint.
Lifecycle: the file is written incrementally by the worker as the scan
runs. While the scan is still running the response returns whatever has
been flushed so far (the publisher uses a line-buffered handle, so each
completed line is on disk by the time it is on the WebSocket). After the
scan terminates the file stays on disk until workspace_cleaner reaps
the parent workspace directory (current default: per
WORKSPACE_ORPHAN_MAX_AGE_SECONDS).
| scan_id required | string <uuid> (Scan Id) |
nullServe the scan's recorded inputs.
Existence-hide comes from get_scan — the same resolver the scan read
uses — so an id in another team is indistinguishable here from one that
never existed. Nothing about this route may answer a question the scan read
would refuse.
A scan with neither half recorded is a 200 with two nulls, not a 404: the scan exists and the honest answer is that nothing was recorded, which a 404 would misreport as "no such scan".
| scan_id required | string <uuid> (Scan Id) |
{- "document": {
- "authors": [
- "string"
], - "byte_size": 0,
- "component_count": 0,
- "created": "string",
- "format": "string",
- "original_filename": "string",
- "serial_number": "string",
- "spec_version": "string",
- "subject": "string",
- "subject_version": "string",
- "supplier": "string",
- "tools": [
- {
- "name": "string",
- "version": "string"
}
]
}, - "kind": "source",
- "manifests": {
- "count": 0,
- "files": [
- {
- "path": "string",
- "sha256": "string",
- "size": 0
}
], - "truncated": true
}, - "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af"
}Start the first scan on a set of freshly registered projects.
The team's concurrent-scan cap is re-counted for each row against the
team's live active-scan total, so a batch starts scans up to the cap and
reports the rest as rate_limited with an estimated wait. It is not a way
around the cap: the cap protects the shared worker pool, and queueing past
it would move the load rather than shed it. Send the remainder again once
the earlier scans finish.
A project that already has a queued or running scan counts as success, for the same reason an existing project does in the project batch: that is the state the caller asked for.
Status is 201 when every row started and 207 when any did not.
| project_ids required | Array of strings <uuid> (Project Ids) [ 1 .. 200 ] items [ items <uuid > ] Projects to scan, at most 200. The team's concurrent-scan cap still applies and is re-counted per row, so a batch starts scans up to the cap and reports the rest as |
Ref (string) or Ref (null) (Ref) Git ref to scan, applied to every row. Omit for the default branch. |
{- "project_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "ref": "string"
}{- "all_succeeded": true,
- "already_existed": 0,
- "created": 0,
- "failed": 0,
- "failed_by_status": {
- "property1": 0,
- "property2": 0
}, - "rows": [
- {
- "detail": "string",
- "index": 0,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "retry_after_seconds": 0,
- "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "status": "created"
}
], - "total": 0
}| project_id required | string <uuid> (Project Id) |
| path required | string (Path) File to read, relative to the source root. |
| raw | boolean (Raw) Default: false When true, stream the FULL member as application/octet-stream (no per-file viewer cap) for download instead of the capped JSON preview. Same path-traversal / symlink defences apply. |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "byte_size": 1071,
- "content": "MIT License\n\nCopyright (c) ...",
- "encoding": "utf-8",
- "license_matches": [
- {
- "end_line": 21,
- "score": 99.5,
- "spdx_id": "MIT",
- "start_line": 1
}
], - "path": "LICENSE",
- "scan_id": "5b6c0f2e-3a1d-4e8a-9b2c-7d4e1f0a9c33",
- "truncated": false
}| project_id required | string <uuid> (Project Id) |
| path | string (Path) Default: "" Directory whose immediate children to list. Empty = root. |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 1-based page index. |
| size | integer (Size) [ 1 .. 500 ] Default: 100 Page size (max 500). |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "entries": [
- {
- "byte_size": 1280,
- "is_dir": false,
- "license_spdx_ids": [
- "MIT"
], - "name": "main.py",
- "path": "src/main.py"
}
], - "page": 1,
- "path": "src",
- "scan_id": "5b6c0f2e-3a1d-4e8a-9b2c-7d4e1f0a9c33",
- "size": 50,
- "total": 1
}| project_id required | string <uuid> (Project Id) |
| format | string (Format) Default: "openvex" Enum: "openvex" "cyclonedx" VEX output format. |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
| upload required | string <application/octet-stream> (Upload) An OpenVEX or CycloneDX VEX JSON document (format auto-detected). |
{- "applied": 0,
- "errors": [
- {
- "detail": "string",
- "product": "string",
- "reason": "unknown_vulnerability",
- "vulnerability": "string"
}
], - "format": "openvex",
- "matched": 0,
- "skipped": 0
}| project_id required | string <uuid> (Project Id) |
| limit | integer (Limit) [ 1 .. 500 ] Default: 50 |
| offset | integer (Offset) >= 0 Default: 0 |
Search (string) or Search (null) (Search) | |
Array of Severity (strings) or Severity (null) (Severity) | |
Array of Status (strings) or Status (null) (Status) | |
Array of License Category (strings) or License Category (null) (License Category) W2 #33 — License risk-axis filter. Repeatable; accepted values: | |
Min Epss (number) or Min Epss (null) (Min Epss) Keep only findings whose CVE has an EPSS exploit-probability >= this threshold, in [0, 1]. CVEs with no published EPSS score are excluded. Omit to disable EPSS filtering. | |
Reachable (string) or Reachable (null) (Reachable) Tri-state reachability filter (v2.3). | |
Sla (string) or Sla (null) (Sla) X1 SLA filter (single value). | |
Assignee (string) or Assignee (null) (Assignee) Ownership filter. | |
| sort | string (Sort) ^(severity|cvss|status|discovered_at|epss|rea... Default: "severity" Sort key. |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "items": [
- {
- "affected_component_count": 1,
- "affected_component_license": "MIT",
- "affected_component_license_category": "allowed",
- "affected_component_name": "lodash",
- "affected_component_version": "4.17.20",
- "analysis_source": "manual",
- "assignee_is_active": true,
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "component_license_category": "conditional",
- "cve_id": "string",
- "cvss_score": 0,
- "discovered_at": "2019-08-24T14:15:22Z",
- "due_on": "2019-08-24",
- "due_source": "sla",
- "effective_due_date": "2019-08-24T14:15:22Z",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "first_detected_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kev": false,
- "kev_due_date": "2021-12-24",
- "reachability_analyzed_at": "2019-08-24T14:15:22Z",
- "reachability_source": "govulncheck",
- "reachable": true,
- "severity": "critical",
- "sla_due_date": "2019-08-24T14:15:22Z",
- "sla_status": "overdue",
- "status": "new",
- "summary": "string",
- "ticket_key": "string",
- "ticket_url": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "limit": 0,
- "offset": 0,
- "severity_distribution": {
- "property1": 0,
- "property2": 0
}, - "total": 0
}The same rows the list endpoint would return, without the paging.
Every filter the list accepts is accepted here and applied by the same code: the export pages the list service rather than rebuilding its query, so a filter that narrows the screen narrows the file identically, and the cross-team check the list performs is the one this performs.
limit and offset are deliberately absent. Exporting "page 3 of
what I am looking at" is not a thing anyone wants, and accepting them
would invite a caller to walk the table with a script.
sort/order are still accepted and still validated (an invalid
value still 422s), but no longer decide the exported rows' order (#463):
the export walks a fixed key (the finding id) instead of the screen's 8
sort modes, so a filtered export that reaches real depth does not pay
for OFFSET's cost growing with it. Kept on the signature rather than
dropped so an existing caller's ?sort=...&order=... keeps 200ing
instead of 422ing on an unknown parameter.
| project_id required | string <uuid> (Project Id) |
Search (string) or Search (null) (Search) | |
Array of Severity (strings) or Severity (null) (Severity) | |
Array of Status (strings) or Status (null) (Status) | |
Array of License Category (strings) or License Category (null) (License Category) | |
Min Epss (number) or Min Epss (null) (Min Epss) | |
Reachable (string) or Reachable (null) (Reachable) | |
Sla (string) or Sla (null) (Sla) | |
Assignee (string) or Assignee (null) (Assignee) | |
| sort | string (Sort) ^(severity|cvss|status|discovered_at|epss|rea... Default: "severity" |
| order | string (Order) ^(asc|desc)$ Default: "desc" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}The "Group by upgrade" view: the resolved scan's OPEN findings grouped by the minimum safe upgrade that clears them, most-actionable first.
Same auth / snapshot semantics as the list endpoint — non-member → 403,
missing project → 404, unresolvable ?scan_id= → 404, no succeeded scan →
200 with an empty clusters and total_findings == 0.
| project_id required | string <uuid> (Project Id) |
| limit | integer (Limit) [ 1 .. 200 ] Default: 50 |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor. Read this surface as of ONE specific succeeded scan instead of the project's current state. Must belong to this project and be succeeded, else 404. Takes precedence over | |
Release (string) or Release (null) (Release) Optional version anchor — read this surface as of the release carrying this label (e.g. '4.0'). Equivalent to looking the label up on |
{- "clusters": [
- {
- "component_name": "lodash",
- "component_purl": "pkg:npm/lodash",
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "current_version": "4.17.19",
- "direct": true,
- "finding_count": 1,
- "findings": [
- {
- "cve_id": "string",
- "epss_score": 0.97123,
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "fixed_version": "4.17.21",
- "kev": false,
- "severity": "critical",
- "status": "new"
}
], - "max_epss": 0.97123,
- "max_severity": "critical",
- "reason": "ok",
- "recommended_version": "4.17.21"
}
], - "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "total_clusters": 0,
- "total_findings": 0,
- "truncated": false
}W2 #33b — apply one VEX transition across many findings in one round-trip.
Per-row failures (404 / 403 / 422) are surfaced in the response envelope so the UI can render "succeeded N · failed M" with per-row details. Only envelope-level shape violations (empty list, > cap, unknown enum) return RFC 7807 — those would still abort a per-row partial commit, so they belong on the envelope rather than masquerading as per-row outcomes.
| project_id required | string <uuid> (Project Id) |
| finding_ids required | Array of strings <uuid> (Finding Ids) [ 1 .. 200 ] items [ items <uuid > ] Finding ids to transition. 1..200 entries; duplicates are deduplicated server-side. Ids that do not exist in THIS project (cross-project / cross-team / never-existed) are reported as a per-row 404 — they do not abort the bulk. |
Justification (string) or Justification (null) (Justification) Free-form note recorded as | |
| target_status required | string (Target Status) Enum: "new" "analyzing" "exploitable" "not_affected" "false_positive" "suppressed" "fixed" Target status applied to every supplied id. Per-row transition-matrix and role checks still run (developer → suppressed is blocked per row even in a bulk that contains it). |
{- "finding_ids": [
- "497f6eca-6276-4993-bfeb-53cbbbba6f08"
], - "justification": "string",
- "target_status": "new"
}{- "failed": 0,
- "results": [
- {
- "allowed_to": [
- "new"
], - "detail": "string",
- "error": "string",
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "status_code": 200,
- "success": true
}
], - "succeeded": 0,
- "target_status": "new",
- "total": 1
}| finding_id required | string <uuid> (Finding Id) |
{- "affected_components": [
- {
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "fixed_version": "string",
- "name": "string",
- "purl": "string",
- "version": "string"
}
], - "analysis_justification": "string",
- "analysis_source": "manual",
- "analysis_state": "string",
- "analyst_user_id": "0983c53a-1216-4076-815a-f64301f7aa2c",
- "analyzed_at": "2019-08-24T14:15:22Z",
- "assignee_is_active": true,
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "created_at": "2019-08-24T14:15:22Z",
- "cve_id": "string",
- "cvss_score": 0,
- "cvss_vector": "string",
- "details": "string",
- "due_on": "2019-08-24",
- "due_source": "sla",
- "effective_due_date": "2019-08-24T14:15:22Z",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "first_detected_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kev": false,
- "kev_due_date": "2026-07-22",
- "manual_due_ignored": false,
- "matching_provenance": {
- "feed_url": "string",
- "id": "string",
- "name": "string"
}, - "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "published_at": "2019-08-24T14:15:22Z",
- "reachability_analyzed_at": "2019-08-24T14:15:22Z",
- "reachability_source": "govulncheck",
- "reachable": true,
- "references": [
- null
], - "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "severity": "critical",
- "sla_due_date": "2019-08-24T14:15:22Z",
- "sla_status": "ok",
- "status": "new",
- "status_history": [
- {
- "action": "string",
- "actor_user_id": "d6ed4497-4325-4995-9f49-e288b7192e46",
- "created_at": "2019-08-24T14:15:22Z",
- "new_status": "new",
- "previous_status": "new",
- "request_id": "string"
}
], - "summary": "string",
- "ticket_check_error": "string",
- "ticket_checked_at": "2019-08-24T14:15:22Z",
- "ticket_key": "string",
- "ticket_resolved": true,
- "ticket_status": "string",
- "ticket_url": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "upgrade_recommendation": {
- "direct": true,
- "finding_count": 0,
- "max_epss": 0.97123,
- "max_severity": "critical",
- "reason": "ok",
- "recommended_version": "2.17.1"
}, - "vex_origin": {
- "author": "string",
- "format": "openvex",
- "id": "string",
- "imported_at": "string",
- "timestamp": "string",
- "vex_status": "string"
}
}| finding_id required | string <uuid> (Finding Id) |
Assignee User Id (string) or Assignee User Id (null) (Assignee User Id) Who owns remediating this finding. Must be an active, non-service account on the project's team, the same rule obligations use. Send | |
Due On (string) or Due On (null) (Due On) Remediation deadline as a calendar date, interpreted in UTC. The EARLIER of this and the per-severity SLA governs, so a date after the policy's is stored but does not move the deadline; the response's | |
If Match (string) or If Match (null) (If Match) Optional optimistic-concurrency token, same contract as the status PATCH: the server compares it against the row's current | |
Ticket Key (string) or Ticket Key (null) (Ticket Key) Ticket identifier, e.g. | |
Ticket Url (string) or Ticket Url (null) (Ticket Url) Where the work is tracked externally. Send |
{- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "due_on": "2019-08-24",
- "if_match": "2019-08-24T14:15:22Z",
- "ticket_key": "string",
- "ticket_url": "string"
}{- "affected_components": [
- {
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "fixed_version": "string",
- "name": "string",
- "purl": "string",
- "version": "string"
}
], - "analysis_justification": "string",
- "analysis_source": "manual",
- "analysis_state": "string",
- "analyst_user_id": "0983c53a-1216-4076-815a-f64301f7aa2c",
- "analyzed_at": "2019-08-24T14:15:22Z",
- "assignee_is_active": true,
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "created_at": "2019-08-24T14:15:22Z",
- "cve_id": "string",
- "cvss_score": 0,
- "cvss_vector": "string",
- "details": "string",
- "due_on": "2019-08-24",
- "due_source": "sla",
- "effective_due_date": "2019-08-24T14:15:22Z",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "first_detected_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kev": false,
- "kev_due_date": "2026-07-22",
- "manual_due_ignored": false,
- "matching_provenance": {
- "feed_url": "string",
- "id": "string",
- "name": "string"
}, - "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "published_at": "2019-08-24T14:15:22Z",
- "reachability_analyzed_at": "2019-08-24T14:15:22Z",
- "reachability_source": "govulncheck",
- "reachable": true,
- "references": [
- null
], - "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "severity": "critical",
- "sla_due_date": "2019-08-24T14:15:22Z",
- "sla_status": "ok",
- "status": "new",
- "status_history": [
- {
- "action": "string",
- "actor_user_id": "d6ed4497-4325-4995-9f49-e288b7192e46",
- "created_at": "2019-08-24T14:15:22Z",
- "new_status": "new",
- "previous_status": "new",
- "request_id": "string"
}
], - "summary": "string",
- "ticket_check_error": "string",
- "ticket_checked_at": "2019-08-24T14:15:22Z",
- "ticket_key": "string",
- "ticket_resolved": true,
- "ticket_status": "string",
- "ticket_url": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "upgrade_recommendation": {
- "direct": true,
- "finding_count": 0,
- "max_epss": 0.97123,
- "max_severity": "critical",
- "reason": "ok",
- "recommended_version": "2.17.1"
}, - "vex_origin": {
- "author": "string",
- "format": "openvex",
- "id": "string",
- "imported_at": "string",
- "timestamp": "string",
- "vex_status": "string"
}
}| finding_id required | string <uuid> (Finding Id) |
If Match (string) or If Match (null) (If Match) Optional optimistic-concurrency token. When supplied, the server compares this against the current row's updated_at. Mismatch → 409 Conflict (RFC 7807). When omitted, the update proceeds without lock (best-effort). | |
Justification (string) or Justification (null) (Justification) Free-form note recorded as analysis_justification. Required by the UI for VEX-significant transitions but enforced softly: the API accepts an empty justification (regulators often re-trigger the transition once with the note attached). | |
| status required | string (Status) Enum: "new" "analyzing" "exploitable" "not_affected" "false_positive" "suppressed" "fixed" Target status. |
{- "if_match": "2019-08-24T14:15:22Z",
- "justification": "string",
- "status": "new"
}{- "affected_components": [
- {
- "component_version_id": "33c04c34-755a-41ca-908a-75da7567be4e",
- "fixed_version": "string",
- "name": "string",
- "purl": "string",
- "version": "string"
}
], - "analysis_justification": "string",
- "analysis_source": "manual",
- "analysis_state": "string",
- "analyst_user_id": "0983c53a-1216-4076-815a-f64301f7aa2c",
- "analyzed_at": "2019-08-24T14:15:22Z",
- "assignee_is_active": true,
- "assignee_user_id": "e942d24d-8cee-4fa2-bf68-164509e32e2f",
- "created_at": "2019-08-24T14:15:22Z",
- "cve_id": "string",
- "cvss_score": 0,
- "cvss_vector": "string",
- "details": "string",
- "due_on": "2019-08-24",
- "due_source": "sla",
- "effective_due_date": "2019-08-24T14:15:22Z",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "first_detected_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kev": false,
- "kev_due_date": "2026-07-22",
- "manual_due_ignored": false,
- "matching_provenance": {
- "feed_url": "string",
- "id": "string",
- "name": "string"
}, - "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "published_at": "2019-08-24T14:15:22Z",
- "reachability_analyzed_at": "2019-08-24T14:15:22Z",
- "reachability_source": "govulncheck",
- "reachable": true,
- "references": [
- null
], - "scan_id": "9a59f0f5-5572-476d-a7fc-c960ef43a5af",
- "severity": "critical",
- "sla_due_date": "2019-08-24T14:15:22Z",
- "sla_status": "ok",
- "status": "new",
- "status_history": [
- {
- "action": "string",
- "actor_user_id": "d6ed4497-4325-4995-9f49-e288b7192e46",
- "created_at": "2019-08-24T14:15:22Z",
- "new_status": "new",
- "previous_status": "new",
- "request_id": "string"
}
], - "summary": "string",
- "ticket_check_error": "string",
- "ticket_checked_at": "2019-08-24T14:15:22Z",
- "ticket_key": "string",
- "ticket_resolved": true,
- "ticket_status": "string",
- "ticket_url": "string",
- "updated_at": "2019-08-24T14:15:22Z",
- "upgrade_recommendation": {
- "direct": true,
- "finding_count": 0,
- "max_epss": 0.97123,
- "max_severity": "critical",
- "reason": "ok",
- "recommended_version": "2.17.1"
}, - "vex_origin": {
- "author": "string",
- "format": "openvex",
- "id": "string",
- "imported_at": "string",
- "timestamp": "string",
- "vex_status": "string"
}
}| finding_id required | string <uuid> (Finding Id) |
{- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "ticket_check_error": "string",
- "ticket_checked_at": "2019-08-24T14:15:22Z",
- "ticket_resolved": true,
- "ticket_status": "string"
}| organization_id required | string <uuid> (Organization Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| organization_id required | string <uuid> (Organization Id) |
{- "component_columns": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "header_text": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "org_label": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "updated_at": "2019-08-24T14:15:22Z",
- "vulnerability_columns": [
- "string"
]
}| organization_id required | string <uuid> (Organization Id) |
Array of Component Columns (strings) or Component Columns (null) (Component Columns) Non-empty subset of ['name', 'version', 'license', 'severity', 'vulns']. Null means every column renders (current behavior). | |
Header Text (string) or Header Text (null) (Header Text) Plain text printed under the report header. Null clears it. | |
Org Label (string) or Org Label (null) (Org Label) Replaces the default brand text in the report header. Null clears it. | |
Array of Vulnerability Columns (strings) or Vulnerability Columns (null) (Vulnerability Columns) Non-empty subset of ['cve', 'cvss', 'summary', 'status'], in canonical order regardless of the order given. Null means every column renders (current behavior). |
{- "component_columns": [
- "string"
], - "header_text": "string",
- "org_label": "string",
- "vulnerability_columns": [
- "string"
]
}{- "component_columns": [
- "string"
], - "created_at": "2019-08-24T14:15:22Z",
- "header_text": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "org_label": "string",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "updated_at": "2019-08-24T14:15:22Z",
- "vulnerability_columns": [
- "string"
]
}| kind required | string (Kind) Which search tab the params belong to: projects, components, vulnerabilities, or licenses. |
| name required | string (Name) [ 1 .. 60 ] characters |
object (Params) The saved query string, replayed verbatim on open. Opaque to the server — it is whatever filters the page carried at save time. |
{- "kind": "string",
- "name": "string",
- "params": { }
}{- "created_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "kind": "string",
- "name": "string",
- "params": { }
}| saved_search_id required | string <uuid> (Saved Search Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "cadence": "string",
- "day_of_week": 0,
- "hour": 0,
- "is_active": true,
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "source": "string",
- "timezone": "string"
}| organization_id required | string <uuid> (Organization Id) |
Cadence (string) or Cadence (null) (Cadence) 'daily' or 'weekly'. Null means this row decides nothing yet. | |
Day Of Week (integer) or Day Of Week (null) (Day Of Week) 0=Monday..6=Sunday. Required for 'weekly', forbidden for 'daily'. | |
Hour (integer) or Hour (null) (Hour) Local hour-of-day (0-23) the schedule fires, read in | |
| is_active | boolean (Is Active) Default: true Whether this row's schedule fires. False opts a project out of an organization default without deleting the row. |
| timezone | string (Timezone) Default: "UTC" IANA zone name the hour/day-of-week are read against. |
{- "cadence": "string",
- "day_of_week": 6,
- "hour": 23,
- "is_active": true,
- "timezone": "UTC"
}{- "cadence": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "day_of_week": 0,
- "hour": 0,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "last_triggered_at": "2019-08-24T14:15:22Z",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "timezone": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| project_id required | string <uuid> (Project Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}| project_id required | string <uuid> (Project Id) |
{- "cadence": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "day_of_week": 0,
- "hour": 0,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "last_triggered_at": "2019-08-24T14:15:22Z",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "timezone": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| project_id required | string <uuid> (Project Id) |
Cadence (string) or Cadence (null) (Cadence) 'daily' or 'weekly'. Null means this row decides nothing yet. | |
Day Of Week (integer) or Day Of Week (null) (Day Of Week) 0=Monday..6=Sunday. Required for 'weekly', forbidden for 'daily'. | |
Hour (integer) or Hour (null) (Hour) Local hour-of-day (0-23) the schedule fires, read in | |
| is_active | boolean (Is Active) Default: true Whether this row's schedule fires. False opts a project out of an organization default without deleting the row. |
| timezone | string (Timezone) Default: "UTC" IANA zone name the hour/day-of-week are read against. |
{- "cadence": "string",
- "day_of_week": 6,
- "hour": 23,
- "is_active": true,
- "timezone": "UTC"
}{- "cadence": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "day_of_week": 0,
- "hour": 0,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "last_triggered_at": "2019-08-24T14:15:22Z",
- "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "timezone": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| q required | string (Q) <= 255 characters Search term. Trimmed; a term shorter than 3 characters yields empty results. Matched case-insensitively as a substring against component name/purl and CVE id. LIKE metacharacters ( |
Kinds (string) or Kinds (null) (Kinds) Comma-separated categories to search: |
{- "components": [
- {
- "component_name": "lodash",
- "project_id": "6f9619ff-8b86-d011-b42d-00cf4fc964ff",
- "project_name": "Payments API",
- "project_slug": "payments-api",
- "purl": "pkg:npm/lodash",
- "version": "4.17.19"
}
], - "query": "lodash",
- "vulnerabilities": [
- {
- "cve_id": "CVE-2021-23337",
- "project_id": "6f9619ff-8b86-d011-b42d-00cf4fc964ff",
- "project_name": "Payments API",
- "project_slug": "payments-api",
- "severity": "high"
}
]
}| kind required | string (Kind) ^(projects|components|vulnerabilities|license... Which result set to page through. |
| q required | string (Q) <= 255 characters |
| page | integer (Page) [ 1 .. 1000000 ] Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 25 |
Array of Severity (strings) or Severity (null) (Severity) | |
Array of Status (strings) or Status (null) (Status) | |
Array of Package Type (strings) or Package Type (null) (Package Type) | |
Array of License Category (strings) or License Category (null) (License Category) |
{- "counts_capped": false,
- "facets": {
- "property1": [
- {
- "count": 0,
- "value": "string"
}
], - "property2": [
- {
- "count": 0,
- "value": "string"
}
]
}, - "items_components": [
- {
- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "component_name": "string",
- "package_type": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "purl": "string",
- "version": "string"
}
], - "items_licenses": [
- {
- "category": "string",
- "component_name": "string",
- "license_id": "38cf2dcf-77be-45c4-b03d-412af2743263",
- "license_name": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "spdx_id": "string",
- "version": "string"
}
], - "items_projects": [
- {
- "archived": false,
- "git_url": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string"
}
], - "items_vulnerabilities": [
- {
- "component_name": "string",
- "cve_id": "string",
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "project_name": "string",
- "project_slug": "string",
- "severity": "string",
- "status": "string",
- "version": "string"
}
], - "kind": "string",
- "page": 1,
- "query": "string",
- "size": 25,
- "total": 0
}| team_id required | string <uuid> (Team Id) |
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "managed_by_user_id": "d4a34414-11a5-40fc-8142-4b94efd0f141"
}
], - "total": 0
}| display_name required | string (Display Name) [ 1 .. 255 ] characters What this automation is, in words, for whoever reads the audit log. |
| role | string (Role) Default: "developer" The account's role within the team, exactly as a person's would be: 'viewer', 'developer' or 'group_admin'. |
| slug required | string (Slug) [ 3 .. 64 ] characters Lowercase letters, digits and hyphens. Becomes the account's identifier, so it is refused rather than reshaped when it does not fit. |
| team_id required | string <uuid> (Team Id) |
{- "display_name": "string",
- "role": "developer",
- "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "managed_by_user_id": "d4a34414-11a5-40fc-8142-4b94efd0f141"
}Deactivate rather than delete.
The row is the actor on every audit entry its keys produced, and deleting it would either orphan those or cascade them away. Deactivating stops the credentials, which is what the caller is asking for.
| service_account_id required | string <uuid> (Service Account Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "managed_by_user_id": "d4a34414-11a5-40fc-8142-4b94efd0f141"
}| service_account_id required | string <uuid> (Service Account Id) |
| steward_user_id required | string <uuid> (Steward User Id) |
{- "steward_user_id": "a0441d2b-6572-4f8e-a034-d29f6e6b8ffa"
}{- "created_at": "2019-08-24T14:15:22Z",
- "email": "string",
- "full_name": "string",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "is_active": true,
- "managed_by_user_id": "d4a34414-11a5-40fc-8142-4b94efd0f141"
}Scoped to the caller's own teams, so the queue never shows another team's work.
{- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "state": "string",
- "target_status": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}
], - "total": 0
}| finding_id required | string <uuid> (Finding Id) |
| justification required | string (Justification) >= 10 characters Why the change is being asked for. Required, and required to be substantive: the approver has nothing else to judge. |
| target_status required | string (Target Status) The status being asked for. Must be one the policy names. |
{- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "justification": "stringstri",
- "target_status": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "state": "string",
- "target_status": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}| approval_id required | string <uuid> (Approval Id) |
| approve required | boolean (Approve) |
Note (string) or Note (null) (Note) Optional reasoning. Kept whether the answer was yes or no. |
{- "approve": true,
- "note": "string"
}{- "created_at": "2019-08-24T14:15:22Z",
- "decided_at": "2019-08-24T14:15:22Z",
- "decided_by_user_id": "c750fc7f-0b29-4c93-a0d7-9578b1a62969",
- "decision_note": "string",
- "finding_id": "feebf65a-2eaa-4fae-aab2-772450efdffe",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "justification": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "state": "string",
- "target_status": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba"
}Reason (string) or Reason (null) (Reason) Why the erasure was asked for, for the operator who will run it and for whoever reviews the decision later. Free text, so do not put the subject's contact details in it. | |
| subject_user_id required | string <uuid> (Subject User Id) |
{- "reason": "string",
- "subject_user_id": "1707c861-e9ed-48f7-9f9f-3d21797cfdf4"
}{- "approved_at": "2019-08-24T14:15:22Z",
- "approved_by_user_id": "6f927876-90f9-4dae-8888-4b498595faf4",
- "created_at": "2019-08-24T14:15:22Z",
- "executed_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "reason": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "state": "string",
- "subject_user_id": "1707c861-e9ed-48f7-9f9f-3d21797cfdf4"
}{- "count": 0,
- "items": [
- {
- "approved_at": "2019-08-24T14:15:22Z",
- "approved_by_user_id": "6f927876-90f9-4dae-8888-4b498595faf4",
- "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "subject_user_id": "1707c861-e9ed-48f7-9f9f-3d21797cfdf4",
- "waiting_days": 0
}
]
}| request_id required | string <uuid> (Request Id) |
{- "approved_at": "2019-08-24T14:15:22Z",
- "approved_by_user_id": "6f927876-90f9-4dae-8888-4b498595faf4",
- "created_at": "2019-08-24T14:15:22Z",
- "executed_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "reason": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "state": "string",
- "subject_user_id": "1707c861-e9ed-48f7-9f9f-3d21797cfdf4"
}| request_id required | string <uuid> (Request Id) |
{- "approved_at": "2019-08-24T14:15:22Z",
- "approved_by_user_id": "6f927876-90f9-4dae-8888-4b498595faf4",
- "created_at": "2019-08-24T14:15:22Z",
- "executed_at": "2019-08-24T14:15:22Z",
- "expires_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "reason": "string",
- "requested_by_user_id": "ed1d5170-d6e9-4e60-8754-78ea9640e9db",
- "state": "string",
- "subject_user_id": "1707c861-e9ed-48f7-9f9f-3d21797cfdf4"
}Keyed off the JWT, never off a parameter.
There is no user_id anywhere in this route. An export endpoint that
accepted one would be an endpoint for reading other people's personal
data, guarded only by whatever check somebody remembered to write.
nullStore a secret and hand back what the setup screen needs to show it.
Behind a step-up. Enrolling on somebody else's account is a takeover: the attacker's authenticator becomes the factor, and the owner is locked out by the control they never set up.
Code (string) or Code (null) (Code) | |
Password (string) or Password (null) (Password) |
{- "code": "string",
- "password": "string"
}{- "mfa_token": "string",
- "provisioning_uri": "string",
- "secret": "string"
}Turn the factor on and return the recovery codes, shown once.
| code required | string (Code) [ 1 .. 64 ] characters |
| mfa_token required | string (Mfa Token) [ 1 .. 4096 ] characters |
{- "code": "string",
- "mfa_token": "string"
}{- "codes": [
- "string"
]
}Issue a new set, invalidating every unused code from the old one.
Behind a step-up, because what it hands back is ten sign-ins that bypass the factor, survive a password change, and are not touched by revoking sessions. Gating that on a session alone means a stolen token is worth ten of them, and a stolen session is the case the factor exists to survive.
Code (string) or Code (null) (Code) | |
Password (string) or Password (null) (Password) |
{- "code": "string",
- "password": "string"
}{- "codes": [
- "string"
]
}Full-row update — every channel field must be supplied.
The body's only meaningful inputs are the four channel toggles. Any
additional fields a caller may send (user_id, id, ...) are
ignored: Pydantic strips unknown fields by default and the service is
keyed off actor.id, never the body.
Chore O / M3 — In-app notifications cannot be disabled. The frontend documents the in-app switch as "rendered but disabled"; this server- side guard closes the API drift where a direct PUT could opt out.
| email_enabled required | boolean (Email Enabled) |
| in_app_enabled required | boolean (In App Enabled) |
| slack_enabled required | boolean (Slack Enabled) |
| teams_enabled required | boolean (Teams Enabled) |
{- "email_enabled": true,
- "in_app_enabled": true,
- "slack_enabled": true,
- "teams_enabled": true
}{- "email_enabled": true,
- "in_app_enabled": true,
- "slack_enabled": true,
- "teams_enabled": true
}{- "has_password": true,
- "items": [
- {
- "created_at": "2019-08-24T14:15:22Z",
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "provider": "github",
- "provider_email": "string",
- "provider_user_id": "string"
}
]
}Remove an OAuth identity link from the authenticated user.
Returns 204 on success. Domain failures map to RFC 7807:
urn:trustedoss:problem:oauth_identity_not_found —
identity does not exist OR belongs to another user
(existence-hide; the two cases share a shape).urn:trustedoss:problem:oauth_unlink_blocks_login —
unlinking would leave the user with no way to authenticate.| identity_id required | string <uuid> (Identity Id) |
{- "detail": "string",
- "instance": "string",
- "status": 0,
- "title": "string",
- "type": "about:blank"
}X-Hub-Signature-256 (string) or X-Hub-Signature-256 (null) (X-Hub-Signature-256) | |
X-Github-Event (string) or X-Github-Event (null) (X-Github-Event) | |
X-Github-Delivery (string) or X-Github-Delivery (null) (X-Github-Delivery) |
nullX-Gitlab-Token (string) or X-Gitlab-Token (null) (X-Gitlab-Token) | |
X-Gitlab-Event (string) or X-Gitlab-Event (null) (X-Gitlab-Event) | |
X-Gitlab-Webhook-Uuid (string) or X-Gitlab-Webhook-Uuid (null) (X-Gitlab-Webhook-Uuid) |
null