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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}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"
}
]
}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" |
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.
Returns the new user (without password). 422 for validation errors, 409 if the email is already registered.
| 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.
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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}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.
{ }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).
{- "status": "ready"
}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 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 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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "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"
}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"
}{- "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
}
]
}| page | integer (Page) >= 1 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 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 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",
- "project_count": 0,
- "slug": "string"
}
], - "page": 0,
- "page_size": 0,
- "total": 0
}| page | integer (Page) >= 1 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",
- "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 |
| 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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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 |
| 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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| role required | string (Role) Either team_admin or developer. |
| 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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "project_count": 0,
- "slug": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}| team_id required | string <uuid> (Team Id) |
| role required | string (Role) Either team_admin or developer. |
| 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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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",
- "role": "string",
- "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
], - "name": "string",
- "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 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 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
}| 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"
}
], - "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"
}
], - "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}{- "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"
}
], - "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}{- "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"
}
], - "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"
}
], - "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"
}
], - "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}Issues a one-shot reset token (bcrypt-hashed in storage) and returns 204.
Phase 6 PR #18 will wire 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 (security-reviewer F5) -------------------
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 Phase 6 PR #18 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. See
docs/v2-execution-plan.md §3.7 for the Phase 6 contract.
| user_id required | string <uuid> (User Id) |
{- "detail": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}Issues a one-shot reset token (bcrypt-hashed in storage) and returns 204.
Phase 6 PR #18 will wire 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 (security-reviewer F5) -------------------
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 Phase 6 PR #18 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. See
docs/v2-execution-plan.md §3.7 for the Phase 6 contract.
| user_id required | string <uuid> (User Id) |
{- "detail": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}| user_id required | string <uuid> (User Id) |
| role required | string (Role) One of super_admin / team_admin / developer. |
Team Id (string) or Team Id (null) (Team Id) Required when role is team_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"
}
], - "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 / team_admin / developer. |
Team Id (string) or Team Id (null) (Team Id) Required when role is team_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"
}
], - "scan_count": 0,
- "updated_at": "2019-08-24T14:15:22Z"
}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 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",
- "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 |
Project Id (string) or Project Id (null) (Project Id) | |
| scope required | string (Scope) Enum: "org" "team" "project" |
Team Id (string) or Team Id (null) (Team Id) |
{- "expires_in_days": 1,
- "name": "string",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "scope": "org",
- "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",
- "project_id": "405d8375-3514-403b-8c43-83ae74cfe0e9",
- "raw_key": "string",
- "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) | |
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 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_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_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) |
{- "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_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_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 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_id required | string <uuid> (Component Id) |
{- "created_at": "2019-08-24T14:15:22Z",
- "dependency_scope": "required",
- "depth": 0,
- "direct": false,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license": "string",
- "license_category": "forbidden",
- "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"
}
]
}Aggregate counts (projects, scans, severities, licenses, approvals) plus the 10 most recent scans, scoped to the caller's accessible projects.
{- "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
}
}Team Id (string) or Team Id (null) (Team Id) | |
| include_revoked | boolean (Include Revoked) Default: false |
| page | integer (Page) >= 1 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 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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}Organization Id (string) or Organization Id (null) (Organization Id) | |
Team Id (string) or Team Id (null) (Team Id) | |
| page | integer (Page) >= 1 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": [
- { }
], - "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": [
- { }
], - "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) | |
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"
}
], - "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": [
- { }
], - "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": [
- { }
], - "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) | |
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"
}
], - "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": [
- { }
], - "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": [
- { }
], - "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": [
- { }
], - "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": { },
- "reference_url": "string",
- "spdx_id": "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" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor (feature #28). When given, list license rows of this SPECIFIC succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour. |
{- "distribution": {
- "allowed": 0,
- "conditional": 0,
- "forbidden": 0,
- "unknown": 0
}, - "items": [
- {
- "affected_count": 1,
- "category": "allowed",
- "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",
- "sample_finding_id": "e96d0bbe-3be6-488b-befa-536867c05879",
- "spdx_id": "string"
}
], - "total": 0
}| unread_only | boolean (Unread Only) Default: false |
| page | integer (Page) >= 1 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
}Team Id (string) or Team Id (null) (Team Id) | |
| include_archived | boolean (Include Archived) Default: false |
Q (string) or Q (null) (Q) | |
| page | integer (Page) >= 1 Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 20 |
{- "items": [
- {
- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "default_branch": "string",
- "description": "string",
- "git_url": "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",
- "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",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}
], - "page": 0,
- "size": 0,
- "total": 0
}Default Branch (string) or Default Branch (null) (Default Branch) | |
Description (string) or Description (null) (Description) | |
Git Url (string) or Git Url (null) (Git Url) | |
| name required | string (Name) [ 1 .. 255 ] characters |
| slug required | string (Slug) [ 1 .. 64 ] characters |
| team_id required | string <uuid> (Team Id) |
| visibility | string (Visibility) Default: "team" Enum: "team" "organization" |
{- "default_branch": "string",
- "description": "string",
- "git_url": "string",
- "name": "string",
- "slug": "string",
- "team_id": "810007d0-bec5-486c-b5d1-28fcd8a079ba",
- "visibility": "team"
}{- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "default_branch": "string",
- "description": "string",
- "git_url": "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",
- "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",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}| project_id required | string <uuid> (Project Id) |
{- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "default_branch": "string",
- "description": "string",
- "git_url": "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",
- "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",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}| project_id required | string <uuid> (Project Id) |
| 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 |
Default Branch (string) or Default Branch (null) (Default Branch) | |
Description (string) or Description (null) (Description) | |
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) | |
Visibility (string) or Visibility (null) (Visibility) |
{- "clear_git_credential": false,
- "default_branch": "string",
- "description": "string",
- "git_credential": "string",
- "git_url": "string",
- "name": "string",
- "visibility": "team"
}{- "archived_at": "2019-08-24T14:15:22Z",
- "created_at": "2019-08-24T14:15:22Z",
- "created_by_user_id": "209f54c4-4c33-43bc-9c6a-ef4c65ad7473",
- "created_by_user_name": "string",
- "default_branch": "string",
- "description": "string",
- "git_url": "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",
- "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",
- "updated_at": "2019-08-24T14:15:22Z",
- "visibility": "team"
}| 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 — BD-style 'Usage' facet. Repeatable; accepted values: | |
| 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 (feature #28). When given, list components of this SPECIFIC succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour. |
{- "items": [
- {
- "component_id": "41afafe5-2a48-424a-baef-34c2ad44ef7b",
- "dependency_scope": "required",
- "depth": 0,
- "direct": false,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "license": "string",
- "license_category": "forbidden",
- "name": "string",
- "purl": "string",
- "severity_max": "critical",
- "version": "string",
- "vulnerability_count": 0
}
], - "limit": 0,
- "offset": 0,
- "total": 0
}| 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": [ ]
}
}| project_id required | string <uuid> (Project Id) |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor (feature #28). When given, aggregate this SPECIFIC succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour. |
{- "current_user_role": "super_admin",
- "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,
- "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,
- "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,
- "vuln_data_available": true
}| project_id required | string <uuid> (Project Id) |
| page | integer (Page) >= 1 Default: 1 |
| size | integer (Size) [ 1 .. 100 ] Default: 20 |
{- "items": [
- {
- "component_count": 42,
- "created_at": "2026-05-22T10:00:00Z",
- "gate_status": "fail",
- "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"
}| 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" |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor (feature #28). When given, the grid reflects this specific succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. |
{- "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",
- "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"
}
], - "spdx_id": "string"
}
], - "limit": 1,
- "offset": 0,
- "total": 0
}| project_id required | string <uuid> (Project Id) |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor (feature #28). When given, evaluate the build gate against this SPECIFIC succeeded scan instead of the project's latest succeeded scan (so the Overview gate card can reflect a pinned release). Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour (the CI contract). |
{- "critical_cve_count": 0,
- "epss_gate_count": 0,
- "epss_threshold": 1,
- "evaluated_at": "2019-08-24T14:15:22Z",
- "forbidden_license_count": 0,
- "gate": "pass",
- "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"
}| scan_id required | string <uuid> (Scan Id) |
| dry_run | boolean (Dry Run) Default: false When |
| pr_number required | integer (Pr Number) [ 1 .. 10000000 ] GitHub PR number. |
| repo_full_name required | string (Repo Full Name) [ 3 .. 140 ] characters GitHub |
{- "dry_run": false,
- "pr_number": 1,
- "repo_full_name": "string"
}{- "body_preview": "string",
- "comment_id": 0,
- "comment_url": "string",
- "gate": "pass",
- "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 |
null| 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 (feature #28). When given, list obligation rows of this SPECIFIC succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour. |
{- "distribution": {
- "property1": 0,
- "property2": 0
}, - "items": [
- {
- "affected_count": 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",
- "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",
- "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_truncated": false,
- "updated_at": "2019-08-24T14:15:22Z"
}| 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 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 ( | |
Scan Id (string) or Scan Id (null) (Scan Id) Optional filter — return only rows where | |
| page | integer (Page) >= 1 Default: 1 1-based page number. |
| page_size | integer (Page Size) [ 1 .. 200 ] Default: 50 Rows per page (1..200, default 50). |
{- "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) |
| format | string (Format) Default: "cyclonedx-json" Enum: "cyclonedx-json" "cyclonedx-xml" "spdx-json" "spdx-tv" SBOM output format. |
Scan Id (string) or Scan Id (null) (Scan Id) Optional release-snapshot anchor (feature #28). When given, export this SPECIFIC succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour. |
| project_id required | string <uuid> (Project Id) |
| page | integer (Page) >= 1 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
}Status (string) or Status (null) (Status) Filter by scan status. | |
| page | integer (Page) >= 1 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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}| 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) |
null| project_id required | string <uuid> (Project Id) |
| path required | string (Path) File to read, relative to the source root. |
Scan Id (string) or Scan Id (null) (Scan Id) Scan to read; defaults to the project's latest scan. | |
| 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. |
{- "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 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) Scan to read; defaults to the project's latest scan. |
{- "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) |
| 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). | |
| 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 (feature #28). When given, list CVE findings of this SPECIFIC succeeded scan instead of the project's latest succeeded scan. Must belong to this project and be succeeded, else 404. Omit for the default latest-succeeded behaviour. |
{- "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",
- "component_license_category": "conditional",
- "cve_id": "string",
- "cvss_score": 0,
- "discovered_at": "2019-08-24T14:15:22Z",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "reachability_analyzed_at": "2019-08-24T14:15:22Z",
- "reachability_source": "govulncheck",
- "reachable": true,
- "severity": "critical",
- "status": "new",
- "summary": "string",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "limit": 0,
- "offset": 0,
- "severity_distribution": {
- "property1": 0,
- "property2": 0
}, - "total": 0
}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",
- "created_at": "2019-08-24T14:15:22Z",
- "cve_id": "string",
- "cvss_score": 0,
- "cvss_vector": "string",
- "details": "string",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "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",
- "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",
- "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",
- "created_at": "2019-08-24T14:15:22Z",
- "cve_id": "string",
- "cvss_score": 0,
- "cvss_vector": "string",
- "details": "string",
- "epss_percentile": 0.99412,
- "epss_score": 0.97123,
- "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
- "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",
- "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",
- "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"
}
}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": [
- {
- "ctx": { },
- "input": null,
- "loc": [
- "string"
], - "msg": "string",
- "type": "string"
}
]
}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